JDK-8176813 : Mac: Failure to exit full-screen programmatically in some cases
  • Type: Bug
  • Component: javafx
  • Sub-Component: window-toolkit
  • Affected Version: 8,9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2017-03-15
  • Updated: 2021-12-18
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Relates :  
Description
There are two problems that can happen when programmatically entering and then exiting full-screen mode. They are likely related to each other, so I am filing one bug for both symptoms. We can split one of the two out into a separate bug later if necessary.

Symptom #1 -- stage.setFullScreen(false) will not exit full-screen if done before the window has finished the animation for expanding the window to fill the screen.

To reproduce this, run the existing test.javafx.stage.RestoreStagePositionTest#testUfullscreenPosition unit test. Because of the short sleep time between submitting the runLater that enters full-screen and submitting the runLater that exits full-screen, the exit is called before the animation is done. It seems that glass does not handle this case gracefully. The window will fail to exit full-screen mode and the test will fail.

java.lang.AssertionError: Assertion failed: excpected 300.0, was: 0.0
	at RestoreStagePositionTest2.fail(RestoreStagePositionTest2.java:62)
	at RestoreStagePositionTest2.assertEquals(RestoreStagePositionTest2.java:78)
	at RestoreStagePositionTest2.testUfullscreenPosition(RestoreStagePositionTest2.java:141)
	at RestoreStagePositionTest2.main(RestoreStagePositionTest2.java:52)


Symptom #2 -- stage.setFullScreen(false) will cause an NPE in leaveNestedEventLoop if done after the window has finished the animation for expanding the window to fill the screen.

To reproduce this, modify the "Thread.sleep(400)" to "Thread.sleep(2000)" and run the test. It may be necessary to click in the window before the exception is delivered.

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
	at javafx.graphics/com.sun.glass.ui.Application.leaveNestedEventLoop(Application.java:540)
	at javafx.graphics/com.sun.glass.ui.mac.MacApplication._enterNestedEventLoopImpl(Native Method)
	at javafx.graphics/com.sun.glass.ui.mac.MacApplication._enterNestedEventLoop(MacApplication.java:109)
	at javafx.graphics/com.sun.glass.ui.Application.enterNestedEventLoop(Application.java:511)
	at javafx.graphics/com.sun.glass.ui.mac.MacView._exitFullscreen(Native Method)
	at javafx.graphics/com.sun.glass.ui.View.exitFullscreen(View.java:792)
	at javafx.graphics/com.sun.javafx.tk.quantum.WindowStage.applyFullScreen(WindowStage.java:720)
	at javafx.graphics/com.sun.javafx.tk.quantum.WindowStage.setFullScreen(WindowStage.java:756)
	at javafx.graphics/javafx.stage.Stage.setFullScreen(Stage.java:666)
	at RestoreStagePositionTest2.lambda$testUfullscreenPosition$4(RestoreStagePositionTest2.java:136)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
	at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)

Comments
I agree with Alexander that this patch looks like it is just masking the symptom rather than fixing the problem. One further comment. The following is an indication that something has gone wrong with the thread state management of the Toolkit: > Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Not on FX application thread; currentThread = JavaFX Application Thread This should not be possible unless there was either a problem recording the JavaFX application thread or if it was subsequently changed (e.g., as part of shutdown).
08-08-2017

Regarding http://cr.openjdk.java.net/~aniyogi/8176813/webrev.00/ What about first part of the issue? It looks like that avoiding NPE only masking the issue, because I am still able to get following exceptions after the fix Exception in thread "JavaFX Application Thread" java.lang.NullPointerException at javafx.graphics/com.sun.glass.ui.Screen.initScreens(Screen.java:412) at javafx.graphics/com.sun.glass.ui.Screen.notifySettingsChanged(Screen.java:381) at javafx.graphics/com.sun.glass.ui.mac.MacApplication._enterNestedEventLoopImpl(Native Method) at javafx.graphics/com.sun.glass.ui.mac.MacApplication._enterNestedEventLoop(MacApplication.java:112) at javafx.graphics/com.sun.glass.ui.Application.enterNestedEventLoop(Application.java:559) at javafx.graphics/com.sun.glass.ui.mac.MacWindow._setView(Native Method) at javafx.graphics/com.sun.glass.ui.Window.setView(Window.java:418) at javafx.graphics/com.sun.javafx.tk.quantum.WindowStage.lambda$setScene$1(WindowStage.java:295) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithRenderLock(QuantumToolkit.java:399) at javafx.graphics/com.sun.javafx.tk.quantum.WindowStage.setScene(WindowStage.java:291) at javafx.graphics/javafx.stage.Window$12.invalidated(Window.java:1142) at javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110) at javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145) at javafx.graphics/javafx.stage.Window.setShowing(Window.java:1186) at javafx.graphics/javafx.stage.Window.hide(Window.java:1211) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418) at java.base/java.security.AccessController.doPrivileged(Native Method) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417) at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96) or (just move mouse over stage) Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Not on FX application thread; currentThread = JavaFX Application Thread at javafx.graphics/com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:246) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:415) at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3799) at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1300(Scene.java:3604) at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1874) at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2613) at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397) at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295) at java.base/java.security.AccessController.doPrivileged(Native Method) at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:381) at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433) at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556) at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942) at javafx.graphics/com.sun.glass.ui.mac.MacView.notifyMouse(MacView.java:127) at javafx.graphics/com.sun.glass.ui.mac.MacApplication._enterNestedEventLoopImpl(Native Method) at javafx.graphics/com.sun.glass.ui.mac.MacApplication._enterNestedEventLoop(MacApplication.java:112) at javafx.graphics/com.sun.glass.ui.Application.enterNestedEventLoop(Application.java:559) at javafx.graphics/com.sun.glass.ui.mac.MacWindow._setView(Native Method) at javafx.graphics/com.sun.glass.ui.Window.setView(Window.java:418) at javafx.graphics/com.sun.javafx.tk.quantum.WindowStage.lambda$setScene$1(WindowStage.java:295) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithRenderLock(QuantumToolkit.java:399) at javafx.graphics/com.sun.javafx.tk.quantum.WindowStage.setScene(WindowStage.java:291) at javafx.graphics/javafx.stage.Window$12.invalidated(Window.java:1142) at javafx.base/javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110) at javafx.base/javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:145) at javafx.graphics/javafx.stage.Window.setShowing(Window.java:1186) at javafx.graphics/javafx.stage.Window.hide(Window.java:1211) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418) at java.base/java.security.AccessController.doPrivileged(Native Method) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417) at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
07-08-2017

enterNestedEventLoopImpl looks unreachable. Any better way to debug the null value? What is the expected default value in such cases?
13-07-2017

It isn't unreachable. enterNestedEventLoopImpl is called from Application::enterNestedEventLoop. When entering full screen on Mac, the call stack is: MacApplication::_enterNestedEventLoopImpl [native] MacApplication::_enterNestedEventLoop Application::enterNestedEventLoop GlassApplication::enterFullScreenExitingLoop [native] GlassViewDelegate::enterFullscreenWithAnimate [native] When exiting full screen, the call stack is similar: ... GlassApplication::enterFullScreenExitingLoop [native] GlassViewDelegate::exitFullscreenWithAnimate [native] I suspect what is happening in the failing case (just a guess) is that the problem occurs when exit fullscreen is called while still in the nested event loop for the enter full screen animation.
13-07-2017

As part of this fix, the following unit tests must be re-enabled (after verifying that they work correctly). test.javafx.scene.RestoreSceneSizeTest#testUnfullscreenSize test.javafx.stage.RestoreStagePositionTest#testUfullscreenPosition The tests will also need to be fixed up (if they haven't already been by the time this bug is fixed) to have a longer delay before exiting full-screen to make sure that the full-screen has happened already on Mac.
16-03-2017

Another simliar unit test is also failing due to this bug: test.javafx.scene.RestoreSceneSizeTest#testUnfullscreenSize java.lang.AssertionError: at org.junit.Assert.fail(Assert.java:91) at org.junit.Assert.assertTrue(Assert.java:43) at org.junit.Assert.assertFalse(Assert.java:68) at org.junit.Assert.assertFalse(Assert.java:79) at test.javafx.scene.RestoreSceneSizeTest.testUnfullscreenSize(RestoreSceneSizeTest.java:112)
15-03-2017

Attached a standalone version of RestoreStagePositionTest that does not depend on JUnit.
15-03-2017

Note: in both cases the Platform.exit() call fails to properly exit the FX toolkit.
15-03-2017