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
This commit is contained in:
Kovid Goyal 2019-05-28 17:54:34 +05:30
parent 39f50830d7
commit abf9c4117d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 61 additions and 34 deletions

View File

@ -13,6 +13,10 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- Fix a missing newline when using the pipe command between the - Fix a missing newline when using the pipe command between the
scrollback and screen contents (:iss:`1642`) 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] 0.14.0 [2019-05-24]
--------------------- ---------------------

View File

@ -366,6 +366,7 @@ void _glfwPollMonitorsNS(void)
free(disconnected); free(disconnected);
free(displays); free(displays);
_glfwRestartDisplayLinks();
} }
// Change the current video mode // Change the current video mode

View File

@ -224,6 +224,7 @@ void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor); void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
float _glfwTransformYNS(float y); float _glfwTransformYNS(float y);
void _glfwClearDisplayLinks(void); void _glfwClearDisplayLinks(void);
void _glfwRestartDisplayLinks(void);
void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start); void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start);
void _glfwDispatchTickCallback(void); void _glfwDispatchTickCallback(void);
void _glfwDispatchRenderFrame(CGDirectDisplayID); void _glfwDispatchRenderFrame(CGDirectDisplayID);

View File

@ -53,6 +53,51 @@ static NSUInteger getStyleMask(_GLFWwindow* window)
return styleMask; 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 // Returns whether the cursor is in the content area of the specified window
// //
static GLFWbool cursorInContentArea(_GLFWwindow* window) static GLFWbool cursorInContentArea(_GLFWwindow* window)
@ -453,6 +498,16 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
_glfwInputWindowFocus(window, GLFW_FALSE); _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 @end
@ -592,7 +647,6 @@ static GLFWapplicationshouldhandlereopenfun handle_reopen_callback = NULL;
_glfwInputLiveResize(window, false); _glfwInputLiveResize(window, false);
} }
- (BOOL)wantsUpdateLayer - (BOOL)wantsUpdateLayer
{ {
return YES; return YES;
@ -1774,14 +1828,6 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
[window->ns.object setAlphaValue: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 void
_glfwDispatchRenderFrame(CGDirectDisplayID displayID) { _glfwDispatchRenderFrame(CGDirectDisplayID displayID) {
_GLFWwindow *w = _glfw.windowListHead; _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) void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start)
{ {
@autoreleasepool { @autoreleasepool {