<Swing Dev> [13] RFR JDK-8213535:Windows HiDPI html lightweight tooltips are truncated

Sergey Bylokhov Sergey.Bylokhov at oracle.com
Sun May 3 22:51:57 UTC 2020


This fix has a long discussion, so I decided to look closely to it, here is one more proposal:

Bug: https://bugs.openjdk.java.net/browse/JDK-8213535
Fix: http://cr.openjdk.java.net/~serb/8213535/webrev.00

Here are some thoughts about the size of the components based on the text:

     Some of the components calculate the size/PreferedSize based on the contains the text. The size of the text maybe calculated only if proper GraphicsConfiguration is used, because different GC may have different default transform and as a result different font metrics and as a result, the same text using the same font will be rendered differently.

Here are common steps which are occurred in the application:
  1. The component is not added to any container/window and some default font render context is used, if the application request the size of the component it will be calculated based on this default context.
  2. If the component is added to the container, it will use render context based on the graphics configuration of the container.
  3. The non-displayable window by default use graphics config of the main screen, and added component should use it as well.
  4. When the window became visible it start to use the proper graphics config, and added component should use it as well.

What could go wrong in the steps above:
  1. The component may cache the size/PreferedSize at step 1, and do not update it at step 2, or step 4(Example JDK-8201552[1])
  2. The application itself may request the size at step 1, and did not recalculate the size after the step 2 or step 4(the current bug)

In the current bug the PopupFactory requests the preferred size of the component which is used as a content of the popup before adding this component to the frame where the popup should become visible. As a result, when the component is added to the frame its size is incorrect since it was calculated using different graphics config, and the actual text which should be rendered into the popup does not fit this size.

Inside PopupFactory we have three different popup types:
  - the lightweight popup is based on the JPanel and used as a container for the JTooltip if it fits the frame size.
  - the medium weight popup used for any other components which fit the frame size.
  - the heavy weight popup used for any components which do not fit the frame size.


Current bug affects lightweight and medium popups only, because the heavy weight popup use its own frame and use proper GC from the beginning.


In the current fix:
   1. The lightweight and medium popups are updated to call pack(NOTE: it is implemented as component.setSize(component.getPreferredSize())) after the popup is added to the frame.
   2. To minimize possible popup “jumping” around the frame(when we recalculate the size), I made popup invisible at the beginning and made it visible after adding to the frame.
   3. Note that I delete invalidate/validate call from the reset(), because the call to pack() will invalidate the component anyway again.
   4. It is necessary to call revalidate(which is shortcut for invalidate/validate) after setVisible=true in the “medium weight” popup because “medium weight” uses AWT component as a container and revalidate is not called automatically, unlike lightweight popup which use Swing.

I have updated the test created for JDK-8201552:
  - The logic of the test still the same but now we additionally test the adding the child component via PopuFactory (PopuFactory will add the component to the frame internally), and will assume that updateComponentTreeUI will change nothing if the size was calculated properly from the beginning.
- During fix development, I have broken a few tests, and a little bit tweak them for the convenience(setLocationRelativeTo was added).


PS: I have found that menu items in some situations do not update its own caches when the size is calculated before adding the menu to the frame, this case was excluded in the updated test, and I'll file a separate bug for it.

[1] https://bugs.openjdk.java.net/browse/JDK-8201552


More information about the swing-dev mailing list