JDK-8305675 : [macos] Stage set to iconified before being shown is displayed on screen
  • Type: Bug
  • Component: javafx
  • Sub-Component: window-toolkit
  • Affected Version: jfx11,8u152,9,jfx20
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: os_x
  • Submitted: 2023-04-05
  • Updated: 2023-11-17
  • Resolved: 2023-11-01
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
jfx22 b16Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
To reproduce this, run the attached test program on macOS 12 (Monterey) or macOS 13 (Ventura)

$ java StartIconified

EXPECTED: The window is initially iconfied and not displayed
ACTUAL: The window is displayed on the screen, and is not iconified

As noted in JDK-8298500, we need automated tests to verify that we can initially show a window that is iconified, maximized, or fullscreen.

The following unit test accidentally tests iconified, and is also failing as a result of this bug.

$ gradle --info -PFULL_TEST=true -PUSE_ROBOT=true :systemTests:test --tests SceneChangeShouldNotFocusStageTest

SceneChangeShouldNotFocusStageTest > windowShouldRemainIconified() STANDARD_ERROR
    Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "javafx.scene.Scene.preferredSize()" because "scene" is null
    	at javafx.graphics@21-internal/javafx.scene.Scene$2.preferredSize(Scene.java:411)
    	at javafx.graphics@21-internal/com.sun.javafx.scene.SceneHelper.preferredSize(SceneHelper.java:65)
    	at javafx.graphics@21-internal/javafx.stage.Window$SceneModel.invalidated(Window.java:867)
    	at javafx.base@21-internal/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    	at javafx.base@21-internal/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
    	at javafx.graphics@21-internal/javafx.stage.Window.setScene(Window.java:823)
    	at javafx.graphics@21-internal/javafx.stage.Stage.setScene(Stage.java:270)
    	at test.robot.javafx.scene.SceneChangeShouldNotFocusStageTest$TestApp.lambda$start$0(SceneChangeShouldNotFocusStageTest.java:77)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.shared.TimelineClipCore.visitKeyFrame(TimelineClipCore.java:239)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.shared.TimelineClipCore.playTo(TimelineClipCore.java:180)
    	at javafx.graphics@21-internal/javafx.animation.Timeline.doPlayTo(Timeline.java:172)
    	at javafx.graphics@21-internal/javafx.animation.AnimationAccessorImpl.playTo(AnimationAccessorImpl.java:39)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.shared.InfiniteClipEnvelope.timePulse(InfiniteClipEnvelope.java:120)
    	at javafx.graphics@21-internal/javafx.animation.Animation.doTimePulse(Animation.java:1189)
    	at javafx.graphics@21-internal/javafx.animation.Animation$1.lambda$timePulse$0(Animation.java:207)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    	at javafx.graphics@21-internal/javafx.animation.Animation$1.timePulse(Animation.java:206)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.AbstractPrimaryTimer.timePulseImpl(AbstractPrimaryTimer.java:343)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.AbstractPrimaryTimer$MainLoop.run(AbstractPrimaryTimer.java:266)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:588)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.PaintCollector.liveRepaintRenderJob(PaintCollector.java:327)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.GlassViewEventHandler$ViewEventNotification.run(GlassViewEventHandler.java:889)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.GlassViewEventHandler$ViewEventNotification.run(GlassViewEventHandler.java:849)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleViewEvent$15(GlassViewEventHandler.java:931)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleViewEvent(GlassViewEventHandler.java:930)
    	at javafx.graphics@21-internal/com.sun.glass.ui.View.handleViewEvent(View.java:535)
    	at javafx.graphics@21-internal/com.sun.glass.ui.View.notifyResize(View.java:875)
    	at javafx.graphics@21-internal/com.sun.glass.ui.mac.MacView.notifyResize(MacView.java:113)
    	at javafx.graphics@21-internal/com.sun.glass.ui.mac.MacWindow._setBounds2(Native Method)
    	at javafx.graphics@21-internal/com.sun.glass.ui.mac.MacWindow._setBounds(MacWindow.java:70)
    	at javafx.graphics@21-internal/com.sun.glass.ui.Window.setBounds(Window.java:589)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.WindowStage.setBounds(WindowStage.java:319)
    	at javafx.graphics@21-internal/javafx.stage.Window$TKBoundsConfigurator.apply(Window.java:1619)
    	at javafx.graphics@21-internal/javafx.stage.Window.applyBounds(Window.java:1477)
    	at javafx.graphics@21-internal/javafx.stage.Window.adjustSize(Window.java:333)
    	at javafx.graphics@21-internal/javafx.stage.Window$SceneModel.invalidated(Window.java:868)
    	at javafx.base@21-internal/javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    	at javafx.base@21-internal/javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147)
    	at javafx.graphics@21-internal/javafx.stage.Window.setScene(Window.java:823)
    	at javafx.graphics@21-internal/javafx.stage.Stage.setScene(Stage.java:270)
    	at test.robot.javafx.scene.SceneChangeShouldNotFocusStageTest$TestApp.lambda$start$0(SceneChangeShouldNotFocusStageTest.java:77)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.shared.TimelineClipCore.visitKeyFrame(TimelineClipCore.java:239)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.shared.TimelineClipCore.playTo(TimelineClipCore.java:180)
    	at javafx.graphics@21-internal/javafx.animation.Timeline.doPlayTo(Timeline.java:172)
    	at javafx.graphics@21-internal/javafx.animation.AnimationAccessorImpl.playTo(AnimationAccessorImpl.java:39)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.shared.InfiniteClipEnvelope.timePulse(InfiniteClipEnvelope.java:120)
    	at javafx.graphics@21-internal/javafx.animation.Animation.doTimePulse(Animation.java:1189)
    	at javafx.graphics@21-internal/javafx.animation.Animation$1.lambda$timePulse$0(Animation.java:207)
    	at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    	at javafx.graphics@21-internal/javafx.animation.Animation$1.timePulse(Animation.java:206)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.AbstractPrimaryTimer.timePulseImpl(AbstractPrimaryTimer.java:343)
    	at javafx.graphics@21-internal/com.sun.scenario.animation.AbstractPrimaryTimer$MainLoop.run(AbstractPrimaryTimer.java:266)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:588)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:572)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:565)
    	at javafx.graphics@21-internal/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:352)
    	at javafx.graphics@21-internal/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

SceneChangeShouldNotFocusStageTest > windowShouldRemainIconified() FAILED
    org.opentest4j.AssertionFailedError: Stage should be iconified ==> expected: <true> but was: <false>
        at app//org.junit.jupiter.api.AssertionUtils.fail(AssertionUtils.java:55)
        at app//org.junit.jupiter.api.AssertTrue.assertTrue(AssertTrue.java:40)
        at app//org.junit.jupiter.api.Assertions.assertTrue(Assertions.java:210)
        at app//test.robot.javafx.scene.SceneChangeShouldNotFocusStageTest.windowShouldRemainIconified(SceneChangeShouldNotFocusStageTest.java:55)


This is a product bug, not a test bug. 
Comments
Changeset: f41e3ec0 Author: Martin Fox <beldenfox@users.noreply.github.com> Committer: Andy Goryachev <angorya@openjdk.org> Date: 2023-11-01 20:38:26 +0000 URL: https://git.openjdk.org/jfx/commit/f41e3ec02bdbdff1417ed20b8e02645348825e4d
01-11-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jfx/pull/1258 Date: 2023-10-12 05:52:04 +0000
26-10-2023

I spun off the exception problem to a separate bug (JDK-8318032). The robot test is exercising a whole bunch of other machinery that's unrelated to the whether or not the Mac window has the correct initial state or not.
12-10-2023

There are two bugs here. The first is that on the Mac you can't show a stage in an iconified state. That is Mac specific and seems easy enough to fix (I'll enter a PR against JDK-8316419). Then there's that slew of exceptions. It's a timing problem and is not platform specific. Fixing it (or even understanding it) is above my pay grade. When the scene is installed in the stage the system tries to resize the window to match. This can trigger a timing pulse which causes the Timeline to install the next scene in the middle of setting up the first one. The re-entered routine is SceneModel.invalidated() in the file java/javafx/stage/Window.java. The result is that the bookkeeping gets permanently messed up and those exceptions keep getting triggered. In some way I do not fully understand this is caused by an interaction with the animation that occurs when the Mac window iconifies into the dock. If the TimeLine is tweaked to push the scene changes out past that animation period the exceptions go away. The bug can be induced on Windows 11 by removing the setIconified(true) call and tweaking the Timeline to speed things up. On Windows 11 the window starts out at some random size and then animates to a new size when the first scene is set. Again, there seems to be an interaction between the Timeline and the timing of that animation.
12-10-2023

This is caused by the same underlying problem as JDK-8316419. I didn't mark it as a duplicate since maximization and iconification should be tested separately.
20-09-2023

NOTE: the failing system test is now skipped on macOS (see JDK-8310024), so the "assumeTrue" will need to be removed as part of this fix.
14-06-2023

The reason this is failing is that a stage that is initially set to iconified is shown as a normal window, not iconified. This can be easily seen by running the attached test program, which is taken from a newly-added manual test under review in https://github.com/openjdk/jfx/pull/1110 I updated the title and Description to more accurately reflect the problem.
13-06-2023

Also fails on macOS Monterey, with JDK 19.0.2
17-04-2023