diff --git a/docs/changelog.rst b/docs/changelog.rst index 4c367b3db..d5eaa720a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -23,6 +23,9 @@ To update |kitty|, :doc:`follow the instructions `. - Fix a regression that caused closing an overlay window to focus the previously focused window rather than the underlying window (:iss:`1720`) +- macOS: Reduce energy consumption when idle by shutting down Apple's display + link thread after 30 second of inactivity (:iss:`1763`) + 0.14.2 [2019-06-09] --------------------- diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index ce081afbf..3f7f8b6dd 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -229,3 +229,4 @@ void _glfwRestartDisplayLinks(void); void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start); void _glfwDispatchTickCallback(void); void _glfwDispatchRenderFrame(CGDirectDisplayID); +void _glfwShutdownCVDisplayLink(unsigned long long, void*); diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 5c4b91965..d98487d68 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -62,6 +62,19 @@ CGDirectDisplayID displayIDForWindow(_GLFWwindow *w) { return (CGDirectDisplayID)-1; } +static unsigned long long display_link_shutdown_timer = 0; +#define DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL 30 + +void +_glfwShutdownCVDisplayLink(unsigned long long timer_id, void *user_data) { + [_glfw.ns.displayLinks.lock lock]; + display_link_shutdown_timer = 0; + for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) { + _GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i]; + if (dl->displayLink) CVDisplayLinkStop(dl->displayLink); + } + [_glfw.ns.displayLinks.lock unlock]; +} static inline void requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) { @@ -74,6 +87,11 @@ requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) { w->ns.renderFrameRequested = true; CGDirectDisplayID displayID = displayIDForWindow(w); [_glfw.ns.displayLinks.lock lock]; + if (display_link_shutdown_timer) { + _glfwPlatformUpdateTimer(display_link_shutdown_timer, DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL, true); + } else { + display_link_shutdown_timer = _glfwPlatformAddTimer(DISPLAY_LINK_SHUTDOWN_CHECK_INTERVAL, false, _glfwShutdownCVDisplayLink, NULL, NULL); + } for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) { _GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i]; if (dl->displayID == displayID) {