From abf9c4117dba5ed0761ec53526da215ce28b12d3 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 28 May 2019 17:54:34 +0530 Subject: [PATCH] macOS: Fix a regression that could cause rendering of a kitty window to occasionally freeze in certain situations, such as moving it between monitors or transitioning from/to fullscreen Fixes #1641 --- docs/changelog.rst | 4 ++ glfw/cocoa_monitor.m | 1 + glfw/cocoa_platform.h | 1 + glfw/cocoa_window.m | 89 ++++++++++++++++++++++++++----------------- 4 files changed, 61 insertions(+), 34 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 3bef6bfb8..5e6a59b0f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -13,6 +13,10 @@ To update |kitty|, :doc:`follow the instructions `. - Fix a missing newline when using the pipe command between the scrollback and screen contents (:iss:`1642`) +- macOS: Fix a regression that could cause rendering of a kitty window + to occasionally freeze in certain situations, such as moving it between + monitors or transitioning from/to fullscreen (:iss:`1641`) + 0.14.0 [2019-05-24] --------------------- diff --git a/glfw/cocoa_monitor.m b/glfw/cocoa_monitor.m index d9fecbfc3..bc55b8b8b 100644 --- a/glfw/cocoa_monitor.m +++ b/glfw/cocoa_monitor.m @@ -366,6 +366,7 @@ void _glfwPollMonitorsNS(void) free(disconnected); free(displays); + _glfwRestartDisplayLinks(); } // Change the current video mode diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 886f553ce..755a605a8 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -224,6 +224,7 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor); float _glfwTransformYNS(float y); void _glfwClearDisplayLinks(void); +void _glfwRestartDisplayLinks(void); void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start); void _glfwDispatchTickCallback(void); void _glfwDispatchRenderFrame(CGDirectDisplayID); diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 4c141ed91..c08a9f080 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -53,6 +53,51 @@ static NSUInteger getStyleMask(_GLFWwindow* window) return styleMask; } + +CGDirectDisplayID displayIDForWindow(_GLFWwindow *w) { + NSWindow *nw = w->ns.object; + NSDictionary *dict = [nw.screen deviceDescription]; + NSNumber *displayIDns = [dict objectForKey:@"NSScreenNumber"]; + if (displayIDns) return [displayIDns unsignedIntValue]; + return (CGDirectDisplayID)-1; +} + + +static inline void +requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) { + if (!callback) { + w->ns.renderFrameRequested = GLFW_FALSE; + w->ns.renderFrameCallback = NULL; + return; + } + w->ns.renderFrameCallback = callback; + w->ns.renderFrameRequested = GLFW_TRUE; + CGDirectDisplayID displayID = displayIDForWindow(w); + [_glfw.ns.displayLinks.lock lock]; + for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) { + _GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i]; + if (dl->displayID == displayID) { + dl->renderFrameRequested = GLFW_TRUE; + if (!dl->displayLinkStarted) { + CVDisplayLinkStart(dl->displayLink); + dl->displayLinkStarted = GLFW_TRUE; + } + break; + } + } + [_glfw.ns.displayLinks.lock unlock]; +} + +void +_glfwRestartDisplayLinks(void) { + _GLFWwindow* window; + for (window = _glfw.windowListHead; window; window = window->next) { + if (window->ns.renderFrameRequested && window->ns.renderFrameCallback) { + requestRenderFrame(window, window->ns.renderFrameCallback); + } + } +} + // Returns whether the cursor is in the content area of the specified window // static GLFWbool cursorInContentArea(_GLFWwindow* window) @@ -453,6 +498,16 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; _glfwInputWindowFocus(window, GLFW_FALSE); } +- (void)windowDidChangeScreen:(NSNotification *)notification +{ + if (window->ns.renderFrameRequested && window->ns.renderFrameCallback) { + // Ensure that if the window changed its monitor, CVDisplayLink + // is running for the new monitor + requestRenderFrame(window, window->ns.renderFrameCallback); + } +} + + @end @@ -592,7 +647,6 @@ static GLFWapplicationshouldhandlereopenfun handle_reopen_callback = NULL; _glfwInputLiveResize(window, false); } - - (BOOL)wantsUpdateLayer { return YES; @@ -1774,14 +1828,6 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) [window->ns.object setAlphaValue:opacity]; } -CGDirectDisplayID displayIDForWindow(_GLFWwindow *w) { - NSWindow *nw = w->ns.object; - NSDictionary *dict = [nw.screen deviceDescription]; - NSNumber *displayIDns = [dict objectForKey:@"NSScreenNumber"]; - if (displayIDns) return [displayIDns unsignedIntValue]; - return (CGDirectDisplayID)-1; -} - void _glfwDispatchRenderFrame(CGDirectDisplayID displayID) { _GLFWwindow *w = _glfw.windowListHead; @@ -1794,31 +1840,6 @@ _glfwDispatchRenderFrame(CGDirectDisplayID displayID) { } } -static inline void -requestRenderFrame(_GLFWwindow *w, GLFWcocoarenderframefun callback) { - if (!callback) { - w->ns.renderFrameRequested = GLFW_FALSE; - w->ns.renderFrameCallback = NULL; - return; - } - w->ns.renderFrameCallback = callback; - w->ns.renderFrameRequested = GLFW_TRUE; - CGDirectDisplayID displayID = displayIDForWindow(w); - [_glfw.ns.displayLinks.lock lock]; - for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) { - _GLFWDisplayLinkNS *dl = &_glfw.ns.displayLinks.entries[i]; - if (dl->displayID == displayID) { - dl->renderFrameRequested = GLFW_TRUE; - if (!dl->displayLinkStarted) { - CVDisplayLinkStart(dl->displayLink); - dl->displayLinkStarted = GLFW_TRUE; - } - break; - } - } - [_glfw.ns.displayLinks.lock unlock]; -} - void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start) { @autoreleasepool {