From 7c3d6b12cd72d73779dbca576bb4fefe4648def1 Mon Sep 17 00:00:00 2001 From: Neil C Smith Date: Tue, 11 Aug 2020 12:22:44 +0100 Subject: [PATCH] Fix window close on macOS; only terminate GLFW if no window open. Trigger sketch shutdown but stop window closing in callback, allowing sketch shutdown to proceed normally. Add extra call to poll GLFW events after window closing - workaround for GLFW issue 1412 pending updated version in LWJGL. Maintain static window count and only call glfwTerminate() on last window close. --- .../java/processing/lwjgl/PSurfaceLWJGL.java | 92 +++++++++++-------- 1 file changed, 54 insertions(+), 38 deletions(-) diff --git a/processing-lwjgl/src/main/java/processing/lwjgl/PSurfaceLWJGL.java b/processing-lwjgl/src/main/java/processing/lwjgl/PSurfaceLWJGL.java index 12aae34..2088347 100644 --- a/processing-lwjgl/src/main/java/processing/lwjgl/PSurfaceLWJGL.java +++ b/processing-lwjgl/src/main/java/processing/lwjgl/PSurfaceLWJGL.java @@ -59,6 +59,8 @@ public class PSurfaceLWJGL implements PSurface { private static final boolean DEBUG_GLFW = Boolean.getBoolean("processing.lwjgl.debug"); + + private static int initCount; @SuppressWarnings("FieldCanBeLocal") private GLDebugMessageCallback debugCallback; @@ -230,6 +232,8 @@ public void initFrame(PApplet sketch) { initWindow(); initInputListeners(); + initCount++; + } @@ -581,7 +585,10 @@ private void initWindow() { })); addWindowCallback(GLFW::glfwSetWindowCloseCallback, GLFWWindowCloseCallback - .create(window1 -> tasks.add(() -> sketch.exit()))); + .create(window1 -> { + glfwSetWindowShouldClose(window1, false); + tasks.add(() -> sketch.exit()); + })); addWindowCallback(GLFW::glfwSetWindowFocusCallback, GLFWWindowFocusCallback .create((window1, focused) -> { @@ -1149,53 +1156,62 @@ public void startThread() { private void handleRun() { this.threadRunning = true; - var sync = new Sync(); - sync.initialise(); - - glfwMakeContextCurrent(window); - - GL.createCapabilities(); - pgl.setThread(Thread.currentThread()); - - if (DEBUG_GLFW) { - setupDebugOpenGLCallback(); - } - - // https://stackoverflow.com/questions/35126615/is-using-a-vao-essential-in-opengl-3-1-with-forward-compatibility-flag-set - glBindVertexArray(glGenVertexArrays()); - - while (this.threadRunning) { - - // Set the swap interval after the setup() to give the user a chance to - // disable V-Sync. As GLFW docs for glfwSwapInterval(int) mention, - // "(...) some swap interval extensions used by GLFW do not allow the swap - // interval to be reset to zero once it has been set to a non-zero value." - if (sketch.frameCount > 0 && this.swapIntervalChanged) { - glfwSwapInterval(this.swapInterval); - this.swapIntervalChanged = false; - } - - // Limit the framerate - sync.sync(frameRate); + try { + var sync = new Sync(); + sync.initialise(); + + glfwMakeContextCurrent(window); + + GL.createCapabilities(); + pgl.setThread(Thread.currentThread()); - for (Runnable t = tasks.poll(); t != null; t = tasks.poll()) { - t.run(); + if (DEBUG_GLFW) { + setupDebugOpenGLCallback(); } - handleDraw(); + // https://stackoverflow.com/questions/35126615/is-using-a-vao-essential-in-opengl-3-1-with-forward-compatibility-flag-set + glBindVertexArray(glGenVertexArrays()); - PApplet.mainThread().runLater(GLFW::glfwPollEvents); + while (this.threadRunning) { + + // Set the swap interval after the setup() to give the user a chance to + // disable V-Sync. As GLFW docs for glfwSwapInterval(int) mention, + // "(...) some swap interval extensions used by GLFW do not allow the swap + // interval to be reset to zero once it has been set to a non-zero value." + if (sketch.frameCount > 0 && this.swapIntervalChanged) { + glfwSwapInterval(this.swapInterval); + this.swapIntervalChanged = false; + } + + // Limit the framerate + sync.sync(frameRate); + + for (Runnable t = tasks.poll(); t != null; t = tasks.poll()) { + t.run(); + } + + handleDraw(); + + PApplet.mainThread().runLater(GLFW::glfwPollEvents); + + } + glBindVertexArray(0); + } catch (Throwable ex) { + this.threadRunning = false; + System.getLogger(PSurfaceLWJGL.class.getName()).log(System.Logger.Level.ERROR, + "Uncaught exception in rendering thread", ex); } - - glBindVertexArray(0); PApplet.mainThread().runLater(() -> { // Need to clean up before exiting - // TODO: Make sure sketch does not System.exits before this could run, e.g. during noLoop() glfwDestroyWindow(window); - glfwTerminate(); - + glfwPollEvents(); + initCount--; + if (initCount <= 0) { + glfwTerminate(); + initCount = 0; + } sketch.exitActual(); });