Browse Source

Add glfwFocusWindow

This removes the (undocumented) behavior where glfwShowWindow would
bring the window to front and set input focus.  That function now
does what it says.
Camilla Berglund 9 years ago
parent
commit
baf574494d
11 changed files with 101 additions and 49 deletions
  1. 1 0
      README.md
  2. 5 0
      docs/news.dox
  3. 7 0
      docs/window.dox
  4. 28 0
      include/GLFW/glfw3.h
  5. 11 10
      src/cocoa_window.m
  6. 5 4
      src/internal.h
  7. 1 1
      src/mir_window.c
  8. 6 7
      src/win32_window.c
  9. 12 3
      src/window.c
  10. 6 6
      src/wl_window.c
  11. 19 18
      src/x11_window.c

+ 1 - 0
README.md

@@ -78,6 +78,7 @@ does not find Doxygen, the documentation will not be generated.
    `glfwGetInstanceProcAddress`, `glfwGetPhysicalDevicePresentationSupport` and
    `glfwCreateWindowSurface` for platform independent Vulkan support
  - Added `glfwMaximizeWindow` and `GLFW_MAXIMIZED` for window maximization
+ - Added `glfwFocusWindow` for giving windows input focus
  - Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting
    absolute and relative window size limits
  - Added `glfwGetKeyName` for querying the layout-specific name of printable

+ 5 - 0
docs/news.dox

@@ -32,6 +32,11 @@ GLFW now supports window maximization with @ref glfwMaximizeWindow and the
 [GLFW_MAXIMIZED](@ref window_attribs_wnd) window hint and attribute.
 
 
+@subsection news_32_focus Window input focus control
+
+GLFW now supports giving windows input focus with @ref glfwFocusWindow.
+
+
 @section news_31 New features in 3.1
 
 These are the release highlights.  For a full list of changes see the

+ 7 - 0
docs/window.dox

@@ -715,6 +715,13 @@ int visible = glfwGetWindowAttrib(window, GLFW_VISIBLE);
 
 @subsection window_focus Window input focus
 
+Windows can be given input focus and brought to the front with @ref
+glfwFocusWindow.
+
+@code
+glfwFocusWindow(window);
+@endcode
+
 If you wish to be notified when a window gains or loses input focus, whether by
 the user, system or your own code, set a focus callback.
 

+ 28 - 0
include/GLFW/glfw3.h

@@ -2283,6 +2283,34 @@ GLFWAPI void glfwShowWindow(GLFWwindow* window);
  */
 GLFWAPI void glfwHideWindow(GLFWwindow* window);
 
+/*! @brief Brings the specified window to front and sets input focus.
+ *
+ *  This function brings the specified window to front and sets input focus.
+ *  The window should already be visible and not iconified.
+ *
+ *  By default, both windowed and full screen mode windows are focused when
+ *  initially created.  Set the [GLFW_FOCUSED](@ref window_hints_wnd) 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.
+ *
+ *  @param[in] window The window to give input focus.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_focus
+ *
+ *  @since Added in version 3.2.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwFocusWindow(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

+ 11 - 10
src/cocoa_window.m

@@ -84,6 +84,7 @@ static GLFWbool enterFullscreenMode(_GLFWwindow* window)
                                     bounds.size.height);
 
     [window->ns.object setFrame:frame display:YES];
+    _glfwPlatformFocusWindow(window);
     return status;
 }
 
@@ -1039,6 +1040,16 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
 }
 
 void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+    [window->ns.object orderFront:nil];
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+    [window->ns.object orderOut:nil];
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
 {
     // Make us the active application
     // HACK: This has been moved here from initializeAppKit to prevent
@@ -1049,16 +1060,6 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
     [window->ns.object makeKeyAndOrderFront:nil];
 }
 
-void _glfwPlatformUnhideWindow(_GLFWwindow* window)
-{
-    [window->ns.object orderFront:nil];
-}
-
-void _glfwPlatformHideWindow(_GLFWwindow* window)
-{
-    [window->ns.object orderOut:nil];
-}
-
 int _glfwPlatformWindowFocused(_GLFWwindow* window)
 {
     return [window->ns.object isKeyWindow];

+ 5 - 4
src/internal.h

@@ -684,15 +684,16 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
  */
 void _glfwPlatformShowWindow(_GLFWwindow* window);
 
-/*! @ingroup platform
- */
-void _glfwPlatformUnhideWindow(_GLFWwindow* window);
-
 /*! @copydoc glfwHideWindow
  *  @ingroup platform
  */
 void _glfwPlatformHideWindow(_GLFWwindow* window);
 
+/*! @copydoc glfwFocusWindow
+ *  @ingroup platform
+ */
+void _glfwPlatformFocusWindow(_GLFWwindow* window);
+
 /*! @brief Returns whether the window is focused.
  *  @ingroup platform
  */

+ 1 - 1
src/mir_window.c

@@ -495,7 +495,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
     mir_surface_spec_release(spec);
 }
 
-void _glfwPlatformUnhideWindow(_GLFWwindow* window)
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
 {
     _glfwInputError(GLFW_PLATFORM_ERROR,
                     "Mir: Unsupported function %s", __PRETTY_FUNCTION__);

+ 6 - 7
src/win32_window.c

@@ -1036,19 +1036,18 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
 void _glfwPlatformShowWindow(_GLFWwindow* window)
 {
     ShowWindow(window->win32.handle, SW_SHOW);
-    BringWindowToTop(window->win32.handle);
-    SetForegroundWindow(window->win32.handle);
-    SetFocus(window->win32.handle);
 }
 
-void _glfwPlatformUnhideWindow(_GLFWwindow* window)
+void _glfwPlatformHideWindow(_GLFWwindow* window)
 {
-    ShowWindow(window->win32.handle, SW_SHOW);
+    ShowWindow(window->win32.handle, SW_HIDE);
 }
 
-void _glfwPlatformHideWindow(_GLFWwindow* window)
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
 {
-    ShowWindow(window->win32.handle, SW_HIDE);
+    BringWindowToTop(window->win32.handle);
+    SetForegroundWindow(window->win32.handle);
+    SetFocus(window->win32.handle);
 }
 
 int _glfwPlatformWindowFocused(_GLFWwindow* window)

+ 12 - 3
src/window.c

@@ -231,10 +231,9 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
     {
         if (wndconfig.visible)
         {
+            _glfwPlatformShowWindow(window);
             if (wndconfig.focused)
-                _glfwPlatformShowWindow(window);
-            else
-                _glfwPlatformUnhideWindow(window);
+                _glfwPlatformFocusWindow(window);
         }
     }
 
@@ -629,6 +628,16 @@ GLFWAPI void glfwHideWindow(GLFWwindow* handle)
     _glfwPlatformHideWindow(window);
 }
 
+GLFWAPI void glfwFocusWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window);
+
+    _GLFW_REQUIRE_INIT();
+
+    _glfwPlatformFocusWindow(window);
+}
+
 GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
 {
     _GLFWwindow* window = (_GLFWwindow*) handle;

+ 6 - 6
src/wl_window.c

@@ -470,18 +470,18 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
     wl_shell_surface_set_toplevel(window->wl.shell_surface);
 }
 
-void _glfwPlatformUnhideWindow(_GLFWwindow* window)
-{
-    // TODO
-    fprintf(stderr, "_glfwPlatformUnhideWindow not implemented yet\n");
-}
-
 void _glfwPlatformHideWindow(_GLFWwindow* window)
 {
     wl_surface_attach(window->wl.surface, NULL, 0, 0);
     wl_surface_commit(window->wl.surface);
 }
 
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+    // TODO
+    fprintf(stderr, "_glfwPlatformFocusWindow not implemented yet\n");
+}
+
 int _glfwPlatformWindowFocused(_GLFWwindow* window)
 {
     // TODO

+ 19 - 18
src/x11_window.c

@@ -763,19 +763,7 @@ static void enterFullscreenMode(_GLFWwindow* window)
                       0);
     }
 
-    if (_glfw.x11.NET_ACTIVE_WINDOW)
-    {
-        // Ask the window manager to raise and focus the GLFW window
-        // Only focused windows with the _NET_WM_STATE_FULLSCREEN state end up
-        // on top of all other windows ("Stacking order" in EWMH spec)
-        sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
-    }
-    else
-    {
-        XRaiseWindow(_glfw.x11.display, window->x11.handle);
-        XSetInputFocus(_glfw.x11.display, window->x11.handle,
-                       RevertToParent, CurrentTime);
-    }
+    _glfwPlatformFocusWindow(window);
 
     if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
     {
@@ -1811,19 +1799,32 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
 
 void _glfwPlatformShowWindow(_GLFWwindow* window)
 {
-    XMapRaised(_glfw.x11.display, window->x11.handle);
+    XMapWindow(_glfw.x11.display, window->x11.handle);
     XFlush(_glfw.x11.display);
 }
 
-void _glfwPlatformUnhideWindow(_GLFWwindow* window)
+void _glfwPlatformHideWindow(_GLFWwindow* window)
 {
-    XMapWindow(_glfw.x11.display, window->x11.handle);
+    XUnmapWindow(_glfw.x11.display, window->x11.handle);
     XFlush(_glfw.x11.display);
 }
 
-void _glfwPlatformHideWindow(_GLFWwindow* window)
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
 {
-    XUnmapWindow(_glfw.x11.display, window->x11.handle);
+    if (_glfw.x11.NET_ACTIVE_WINDOW)
+    {
+        // Ask the window manager to raise and focus the GLFW window
+        // Only focused windows with the _NET_WM_STATE_FULLSCREEN state end up
+        // on top of all other windows ("Stacking order" in EWMH spec)
+        sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
+    }
+    else
+    {
+        XRaiseWindow(_glfw.x11.display, window->x11.handle);
+        XSetInputFocus(_glfw.x11.display, window->x11.handle,
+                       RevertToParent, CurrentTime);
+    }
+
     XFlush(_glfw.x11.display);
 }