fix blank screen on macOS resume from sleep

This commit is contained in:
Jorge Silva 2026-02-17 17:56:14 +00:00
parent 76a29273c8
commit adc97bc117
No known key found for this signature in database
GPG key ID: FCEC6724630D316D
5 changed files with 70 additions and 1 deletions

View file

@ -3818,6 +3818,51 @@ GLFWAPI void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun
requestRenderFrame((_GLFWwindow*)w, callback);
}
GLFWAPI bool glfwCocoaRecreateGLDrawable(GLFWwindow *w) {
_GLFWwindow* window = (_GLFWwindow*)w;
if (window->context.client == GLFW_NO_API) return false;
@try {
// Save current state
NSOpenGLPixelFormat *pixelFormat = window->context.nsgl.pixelFormat;
NSOpenGLContext *oldContext = window->context.nsgl.object;
// Create a new context sharing resources with the old one
NSOpenGLContext *newContext = [[NSOpenGLContext alloc]
initWithFormat:pixelFormat
shareContext:oldContext];
if (newContext == nil) return false;
// Copy settings from old context
GLint opacity = 0;
[oldContext getValues:&opacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
[newContext setValues:&opacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
GLint interval = 0;
[newContext setValues:&interval forParameter:NSOpenGLContextParameterSwapInterval];
// Detach old context
[NSOpenGLContext clearCurrentContext];
[oldContext clearDrawable];
// Attach new context to the view
[window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.retina];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[newContext setView:window->ns.view];
#pragma clang diagnostic pop
[newContext makeCurrentContext];
[newContext update];
// Replace context
window->context.nsgl.object = newContext;
[oldContext release];
} @catch (NSException *e) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to recreate NSGL context: %s (%s)", [[e name] UTF8String], [[e reason] UTF8String]);
return false;
}
return true;
}
GLFWAPI GLFWcocoarenderframefun glfwCocoaSetWindowResizeCallback(GLFWwindow *w, GLFWcocoarenderframefun cb) {
_GLFWwindow* window = (_GLFWwindow*)w;
GLFWcocoarenderframefun current = window->ns.resizeCallback;

View file

@ -309,6 +309,7 @@ def generate_wrappers(glfw_header: str) -> None:
GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback)
uint32_t glfwGetCocoaKeyEquivalent(uint32_t glfw_key, int glfw_mods, int* cocoa_mods)
void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback)
bool glfwCocoaRecreateGLDrawable(GLFWwindow *w)
GLFWcocoarenderframefun glfwCocoaSetWindowResizeCallback(GLFWwindow *w, GLFWcocoarenderframefun callback)
void* glfwGetX11Display(void)
unsigned long glfwGetX11Window(GLFWwindow* window)

3
kitty/glfw-wrapper.c generated
View file

@ -476,6 +476,9 @@ load_glfw(const char* path) {
*(void **) (&glfwCocoaRequestRenderFrame_impl) = dlsym(handle, "glfwCocoaRequestRenderFrame");
if (glfwCocoaRequestRenderFrame_impl == NULL) dlerror(); // clear error indicator
*(void **) (&glfwCocoaRecreateGLDrawable_impl) = dlsym(handle, "glfwCocoaRecreateGLDrawable");
if (glfwCocoaRecreateGLDrawable_impl == NULL) dlerror(); // clear error indicator
*(void **) (&glfwCocoaSetWindowResizeCallback_impl) = dlsym(handle, "glfwCocoaSetWindowResizeCallback");
if (glfwCocoaSetWindowResizeCallback_impl == NULL) dlerror(); // clear error indicator

8
kitty/glfw-wrapper.h generated
View file

@ -1131,7 +1131,9 @@ typedef enum {
typedef struct GLFWDropEvent {
GLFWDropEventType type;
const char **mimes; size_t num_mimes;
double xpos, ypos; // Only valid for GLFW_DROP_ENTER and GLFW_DROP_MOVE
// Positions are only valid for GLFW_DROP_ENTER and GLFW_DROP_MOVE.
// They are in window co-ordinates same as for mouse events
double xpos, ypos;
bool from_self; // Only valid upto GLFW_DROP_DROP
ssize_t (*read_data)(GLFWwindow *w, struct GLFWDropEvent* ev, char *buffer, size_t sz); // Only valid for GLFW_DROP_DATA_AVAILABLE
void (*finish_drop)(GLFWwindow *w, GLFWDragOperationType op); // Only valid for GLFW_DROP_DROP and GLFW_DROP_DATA_AVAILABLE
@ -2464,6 +2466,10 @@ typedef void (*glfwCocoaRequestRenderFrame_func)(GLFWwindow*, GLFWcocoarenderfra
GFW_EXTERN glfwCocoaRequestRenderFrame_func glfwCocoaRequestRenderFrame_impl;
#define glfwCocoaRequestRenderFrame glfwCocoaRequestRenderFrame_impl
typedef bool (*glfwCocoaRecreateGLDrawable_func)(GLFWwindow*);
GFW_EXTERN glfwCocoaRecreateGLDrawable_func glfwCocoaRecreateGLDrawable_impl;
#define glfwCocoaRecreateGLDrawable glfwCocoaRecreateGLDrawable_impl
typedef GLFWcocoarenderframefun (*glfwCocoaSetWindowResizeCallback_func)(GLFWwindow*, GLFWcocoarenderframefun);
GFW_EXTERN glfwCocoaSetWindowResizeCallback_func glfwCocoaSetWindowResizeCallback_impl;
#define glfwCocoaSetWindowResizeCallback glfwCocoaSetWindowResizeCallback_impl

View file

@ -11,6 +11,7 @@
#include "control-codes.h"
#include <structmember.h>
#include "glfw-wrapper.h"
#include "gl-wrapper.h"
#ifdef __APPLE__
#include "cocoa_window.h"
#else
@ -346,6 +347,19 @@ window_iconify_callback(GLFWwindow *window, int iconified) {
static void
cocoa_out_of_sequence_render(OSWindow *window) {
make_os_window_context_current(window);
// On macOS Tahoe, the default framebuffer can become undefined during
// screen change events. Try to recover by recreating the drawable. See #9463
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
if (!glfwCocoaRecreateGLDrawable(window->handle) ||
glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
window->needs_render = true;
request_tick_callback();
return;
}
}
window->needs_render = true;
bool rendered = false;
if (window->fonts_data->sprite_map) rendered = render_os_window(window, monotonic(), true);