On Fri, 24 Feb 2023 04:58:12 GMT, Phil Race <p...@openjdk.org> wrote:

> > > And if a default font prevents the FontUIResource from being installed, 
> > > how does it get installed the in the first place ?
> > > Perhaps that first time the component has no peer and it really is null ?
> > 
> > 
> > The font is null when it's created. Calling `getFont` causes it to go up 
> > the hierarchy, if it has a parent. The UI looks to be initialized (and thus 
> > a font is set) before `getFont` is called.
> 
> That is what I guessed. Accidental or deliberate ? I'd have to spend time to 
> know.

This is the code of `Component.getFont`:
https://github.com/openjdk/jdk/blob/b4ea80731c6c0a0328a9801590ba5b081f08c3bd/src/java.desktop/share/classes/java/awt/Component.java#L1912-L1927

Until the UI is shown, there's no heavyweight peer, so the default font doesn't 
get set.

Even more, a `UI` instance is set from a component constructor:

https://github.com/openjdk/jdk/blob/b4ea80731c6c0a0328a9801590ba5b081f08c3bd/src/java.desktop/share/classes/javax/swing/JLabel.java#L176-L182

https://github.com/openjdk/jdk/blob/b4ea80731c6c0a0328a9801590ba5b081f08c3bd/src/java.desktop/share/classes/javax/swing/JPanel.java#L85-L90

Thus, a font is (always) set on a `JComponent` when the constructor is called, 
the default L&F font would be an instance of `UIResource`.

However, if the font is reset to `null`, the default font (of heavyweight) 
components / peers comes into play.

The default font gets set in `getGraphics`:

https://github.com/openjdk/jdk/blob/b4ea80731c6c0a0328a9801590ba5b081f08c3bd/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java#L640-L643

https://github.com/openjdk/jdk/blob/b4ea80731c6c0a0328a9801590ba5b081f08c3bd/src/java.desktop/unix/classes/sun/awt/X11/XWindow.java#L380-L383

> > > FontUIResource is something devised by Swing, for Swing.
> > > Making AWT components depend on it for the convenience of Swing is 
> > > backwards.
> > 
> > D'oh.

I agree. **AWT should not depend on Swing**.

> > Sounds like the path would be to undo my last commit and just put a note in 
> > the code.
> 
> But then there'd either be the correct font not installed or something else 
> bad ?
> How would a note in the code help ?
> 
> Maybe we are going about this all wrong ?
> Maybe uninstall isn't needed ?
> What are the rules (set by Swing?) for what a L&F should do when installing a 
> UI ? If it is "if there is a FontUIResource, then feel free to replace it 
> with yours" then may be everything in this PR (at least about fonts) is 
> un-needed ?

With where the testing led us, I'm inclined to think that the omission of 
nullifying the font in `uninstallUI` wasn't accidental but rather a deliberate 
decision.

Yes, a `Font` object gets “leaked” after `UI` is uninstalled from a 
`JComponent`. In majority of cases `uninstallUI` is followed by `installUI` for 
another Look-and-Feel. (Without a UI delegate, any `JComponent` is unusable.) 
As such, the `Font` object gets replaced with a newer one if the previous one 
is `UIResource` or remains intact if it's not `UIResource`, which likely means 
it was explicitly set by an app developer.

The common rule for Swing: if a property is `UIResource`, replace it with a new 
default; otherwise preserve the property, don't change it. From this point of 
view, all the properties of a Swing component could remain untouched in 
`uninstallUI`. At the same time, many properties are reset to `null`.

There are issues where font doesn't get reset even though it should. The latest 
example that comes to my mind is 
[JDK-6753661](https://bugs.openjdk.org/browse/JDK-6753661) and #12180. Were 
there others?

This current bug [JDK-8278620](https://bugs.openjdk.org/browse/JDK-8278620) was 
submitted as the result of work on 
[JDK-8277817](https://bugs.openjdk.org/browse/JDK-8277817) and #6603 where an 
object had been serialized, if I remember correctly, but the serialized form 
cannot be read because a class is removed in a later version of JDK. (The 
`java/awt/dnd/BadSerializationTest/BadSerializationTest.java` test seems to do 
the wrong thing: it reads a serialized version of a Swing object which was 
saved by a previous version of JDK, which isn't supported and which was 
[mentioned in the 
comments](https://github.com/openjdk/jdk/pull/6603#issuecomment-991295599).)

The description of JDK-8278620 states `BasicListUI` correctly uninstalls all 
its properties, *including the font_. Why is it not affected by the problem 
we're seeing here where the font gets reset to a non-`ResourceUI` font from the 
heavyweight peer of the frame?

> This is code relied upon by tens of thousands of applications written over a 
> period of 25 years. A change like this is really risky, when you consider 
> that there are probably 10 times more apps than there are Swing regresssion 
> tests .. and only a few of the regression (and other) tests cover this kind 
> of scenario.
> 
> Testing on every platform of every test we have is a bare minimum.
> 
> In the end my point is that unless (and until) we see some application 
> complain, these proactive changes are a bad trade-off.

Perhaps, font property should be *left untouched* just like it is now. However, 
resetting the color properties — foreground and background — doesn't seem to 
cause any issues. As such, the scope of this PR could be reduced to adding the 
`LookAndFeel.uninstallColors` method and using it in UI classes.

As a matter of fact, I ran the client tests with the latest changeset. The set 
of failing tests [remains the 
same](https://github.com/openjdk/jdk/pull/10565#issuecomment-1354064460):

* `javax/swing/GraphicsConfigNotifier/StalePreferredSize.java` (on Windows only)
* one closed test;
* one JCK test.

Only the `sanity/client/SwingSet/src/SwingSet2DemoTest.java` test is gone from 
the list of failures.

So, this hasn't helped.

-------------

PR: https://git.openjdk.org/jdk/pull/10565

Reply via email to