From dcb2d95f9a9dc7d95a8d69b98684ee24bd50bd4b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 18 Feb 2019 09:34:26 +0530 Subject: [PATCH] GLFW: Add support for window occluded notifications on macOS Based on: https://github.com/glfw/glfw/pull/1123 --- glfw/cocoa_window.m | 10 +++++++++ glfw/glfw3.h | 49 +++++++++++++++++++++++++++++++++++++++++++- glfw/internal.h | 3 +++ glfw/null_window.c | 5 +++++ glfw/window.c | 21 +++++++++++++++++++ glfw/wl_window.c | 5 +++++ glfw/x11_window.c | 5 +++++ kitty/glfw-wrapper.c | 3 +++ kitty/glfw-wrapper.h | 28 ++++++++++++++++++++++++- 9 files changed, 127 insertions(+), 2 deletions(-) diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 8db72fdf5..2ca55f7a9 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -425,6 +425,11 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; _glfwInputWindowPos(window, x, y); } +- (void)windowDidChangeOcclusionState:(NSNotification *)notification +{ + _glfwInputWindowOcclusion(window, !([window->ns.object occlusionState] & NSWindowOcclusionStateVisible)); +} + - (void)windowDidMiniaturize:(NSNotification *)notification { if (window->monitor) @@ -1671,6 +1676,11 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window) return [window->ns.object isKeyWindow]; } +int _glfwPlatformWindowOccluded(_GLFWwindow* window) +{ + return !([window->ns.object occlusionState] & NSWindowOcclusionStateVisible); +} + int _glfwPlatformWindowIconified(_GLFWwindow* window) { return [window->ns.object isMiniaturized]; diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 081e733ab..456e6497a 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -828,7 +828,11 @@ extern "C" { * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib). */ #define GLFW_FOCUS_ON_SHOW 0x0002000C - +/*! @brief Occlusion window attribute + * + * Occlusion [window attribute](@ref GLFW_OCCLUDED_attrib). + */ +#define GLFW_OCCLUDED 0x0002000D /*! @brief Framebuffer bit depth hint. * * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). @@ -1246,6 +1250,24 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); +/*! @brief The function signature for window occlusion callbacks. + * + * This is the function signature for window occlusion callback functions. + * + * @param[in] window The window whose occlusion state changed. + * @param[in] occluded `GLFW_TRUE` if the window was occluded, or `GLFW_FALSE` + * if the window is no longer occluded. + * + * @sa @ref window_occlusion + * @sa @ref glfwSetWindowOcclusionCallback + * + * @since Added in version 3.3. + * + * @ingroup window + */ +typedef void (* GLFWwindowocclusionfun)(GLFWwindow*, bool); + + /*! @brief The function signature for window iconify/restore callbacks. * * This is the function signature for window iconify/restore callback @@ -3583,6 +3605,31 @@ GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GL */ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun); +/*! @brief Sets the occlusion callback for the specified window. + * + * This function sets the occlusion callback of the specified window, which is + * called when the window becomes (fully) occluded by other windows or when (a + * part of) the window becomes visible again because an overlapping window is + * moved away. + * + * @param[in] window The window whose callback to set. + * @param[in] cbfun The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_occlusion + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI GLFWwindowocclusionfun glfwSetWindowOcclusionCallback(GLFWwindow* window, GLFWwindowocclusionfun cbfun); + /*! @brief Sets the iconify callback for the specified window. * * This function sets the iconification callback of the specified window, which diff --git a/glfw/internal.h b/glfw/internal.h index b4e7b04f6..6e118133b 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -408,6 +408,7 @@ struct _GLFWwindow GLFWwindowclosefun close; GLFWwindowrefreshfun refresh; GLFWwindowfocusfun focus; + GLFWwindowocclusionfun occlusion; GLFWwindowiconifyfun iconify; GLFWwindowmaximizefun maximize; GLFWframebuffersizefun fbsize; @@ -670,6 +671,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); int _glfwPlatformWindowFocused(_GLFWwindow* window); +int _glfwPlatformWindowOccluded(_GLFWwindow* window); int _glfwPlatformWindowIconified(_GLFWwindow* window); int _glfwPlatformWindowVisible(_GLFWwindow* window); int _glfwPlatformWindowMaximized(_GLFWwindow* window); @@ -712,6 +714,7 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex); ////////////////////////////////////////////////////////////////////////// void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused); +void _glfwInputWindowOcclusion(_GLFWwindow* window, GLFWbool occluded); void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos); void _glfwInputWindowSize(_GLFWwindow* window, int width, int height); void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height); diff --git a/glfw/null_window.c b/glfw/null_window.c index 2823e1775..bbb57f7b9 100644 --- a/glfw/null_window.c +++ b/glfw/null_window.c @@ -232,6 +232,11 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window) return GLFW_FALSE; } +int _glfwPlatformWindowOccluded(_GLFWwindow* window) +{ + return GLFW_FALSE; +} + int _glfwPlatformWindowIconified(_GLFWwindow* window) { return GLFW_FALSE; diff --git a/glfw/window.c b/glfw/window.c index e7e82f6f5..0658a2e1a 100644 --- a/glfw/window.c +++ b/glfw/window.c @@ -88,6 +88,14 @@ _GLFWwindow* _glfwWindowForId(GLFWid id) { return NULL; } +// Notifies shared code that a window's occlusion state has changed +// +void _glfwInputWindowOcclusion(_GLFWwindow* window, GLFWbool occluded) +{ + if (window->callbacks.occlusion) + window->callbacks.occlusion((GLFWwindow*) window, occluded); +} + // Notifies shared code that a window has moved // The position is specified in content area relative screen coordinates // @@ -867,6 +875,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) return window->focusOnShow; case GLFW_TRANSPARENT_FRAMEBUFFER: return _glfwPlatformFramebufferTransparent(window); + case GLFW_OCCLUDED: + return _glfwPlatformWindowOccluded(window); case GLFW_RESIZABLE: return window->resizable; case GLFW_DECORATED: @@ -1068,6 +1078,17 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle, return cbfun; } +GLFWAPI GLFWwindowocclusionfun glfwSetWindowOcclusionCallback(GLFWwindow* handle, + GLFWwindowocclusionfun cbfun) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(window->callbacks.occlusion, cbfun); + return cbfun; +} + GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle, GLFWwindowiconifyfun cbfun) { diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 8ff6bad04..18286708a 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -1239,6 +1239,11 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window) return _glfw.wl.keyboardFocus == window; } +int _glfwPlatformWindowOccluded(_GLFWwindow* window) +{ + return GLFW_FALSE; +} + int _glfwPlatformWindowIconified(_GLFWwindow* window) { // wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 83a9fe928..467b8338a 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -2283,6 +2283,11 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window) return window->x11.handle == focused; } +int _glfwPlatformWindowOccluded(_GLFWwindow* window) +{ + return GLFW_FALSE; +} + int _glfwPlatformWindowIconified(_GLFWwindow* window) { return getWindowState(window) == IconicState; diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index dbd2ca3a2..c5e528205 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -197,6 +197,9 @@ load_glfw(const char* path) { *(void **) (&glfwSetWindowFocusCallback_impl) = dlsym(handle, "glfwSetWindowFocusCallback"); if (glfwSetWindowFocusCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowFocusCallback with error: %s", dlerror()); + *(void **) (&glfwSetWindowOcclusionCallback_impl) = dlsym(handle, "glfwSetWindowOcclusionCallback"); + if (glfwSetWindowOcclusionCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowOcclusionCallback with error: %s", dlerror()); + *(void **) (&glfwSetWindowIconifyCallback_impl) = dlsym(handle, "glfwSetWindowIconifyCallback"); if (glfwSetWindowIconifyCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowIconifyCallback with error: %s", dlerror()); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index e776027ca..666da732f 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -585,7 +585,11 @@ * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib). */ #define GLFW_FOCUS_ON_SHOW 0x0002000C - +/*! @brief Occlusion window attribute + * + * Occlusion [window attribute](@ref GLFW_OCCLUDED_attrib). + */ +#define GLFW_OCCLUDED 0x0002000D /*! @brief Framebuffer bit depth hint. * * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). @@ -1003,6 +1007,24 @@ typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); */ typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); +/*! @brief The function signature for window occlusion callbacks. + * + * This is the function signature for window occlusion callback functions. + * + * @param[in] window The window whose occlusion state changed. + * @param[in] occluded `GLFW_TRUE` if the window was occluded, or `GLFW_FALSE` + * if the window is no longer occluded. + * + * @sa @ref window_occlusion + * @sa @ref glfwSetWindowOcclusionCallback + * + * @since Added in version 3.3. + * + * @ingroup window + */ +typedef void (* GLFWwindowocclusionfun)(GLFWwindow*, bool); + + /*! @brief The function signature for window iconify/restore callbacks. * * This is the function signature for window iconify/restore callback @@ -1641,6 +1663,10 @@ typedef GLFWwindowfocusfun (*glfwSetWindowFocusCallback_func)(GLFWwindow*, GLFWw glfwSetWindowFocusCallback_func glfwSetWindowFocusCallback_impl; #define glfwSetWindowFocusCallback glfwSetWindowFocusCallback_impl +typedef GLFWwindowocclusionfun (*glfwSetWindowOcclusionCallback_func)(GLFWwindow*, GLFWwindowocclusionfun); +glfwSetWindowOcclusionCallback_func glfwSetWindowOcclusionCallback_impl; +#define glfwSetWindowOcclusionCallback glfwSetWindowOcclusionCallback_impl + typedef GLFWwindowiconifyfun (*glfwSetWindowIconifyCallback_func)(GLFWwindow*, GLFWwindowiconifyfun); glfwSetWindowIconifyCallback_func glfwSetWindowIconifyCallback_impl; #define glfwSetWindowIconifyCallback glfwSetWindowIconifyCallback_impl