RFR: 8276849: Refresh the window icon on graphics configuration changes [v3]
Alexey Ivanov
aivanov at openjdk.java.net
Mon Feb 21 13:02:51 UTC 2022
On Mon, 21 Feb 2022 07:57:32 GMT, Emmanuel Bourg <duke at openjdk.java.net> wrote:
>> When a list of icons is set on a window, the most appropiate icon is selected depending on the graphics configuration. But if the graphics configuration changes (because the window is moved to a different screen, or because the DPI settings of the screen is changed), the frame icon isn't updated.
>>
>> Here is an example illustrating the issue:
>>
>> public static void main(String[] args) throws Exception {
>> SwingUtilities.invokeLater(() -> {
>> JFrame frame = new JFrame("Window Icon Test");
>> frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
>> frame.setSize(400, 300);
>> frame.setVisible(true);
>>
>> List<Image> images = new ArrayList<>();
>> for (int size = 16; size <= 32; size++) {
>> // create an image displaying the size used
>> BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
>> Graphics2D g = image.createGraphics();
>> g.setFont(new Font("dialog", Font.BOLD, 12));
>> g.setColor(Color.BLACK);
>> g.drawString(String.valueOf(size), 0, size - (size - g.getFont().getSize()) / 2);
>> images.add(image);
>> }
>>
>> frame.setIconImages(images);
>> });
>> }
>>
>> On Windows if the screen scaling is set to 100% the 16x16 icon is picked from the list. If the scaling of the screen is set to 150% while the application is running, the 16x16 icon is upscaled and looks blurry.
>>
>> A way to work around this issue is to listen for graphics configuration changes with:
>>
>> frame.addPropertyChangeListener("graphicsConfiguration", event -> frame.setIconImages(frame.getIconImages()));
>>
>>
>> Ideally this should be done automatically by the JDK. Maybe the `WindowPeer` could call `updateIconImages()` when `updateGraphicsData()` or `displayChanged()` is invoked?
>
> Emmanuel Bourg has updated the pull request incrementally with five additional commits since the last revision:
>
> - Test case for the window icon update on DPI change (other changes)
> - Test case for the window icon update on DPI change (@compile not needed)
> - Test case for the window icon update on DPI change (center the frame)
> - Test case for the window icon update on DPI change (specific message for timeouts)
> - Test case for the window icon update on DPI change (icon with a white background and centered text)
Changes requested by aivanov (Reviewer).
test/jdk/java/awt/Window/WindowIconUpdateOnDPIChanging/WindowIconUpdateOnDPIChangingTest.java line 79:
> 77: SwingUtilities.invokeLater(WindowIconUpdateOnDPIChangingTest::createUI);
> 78: if (!countDownLatch.await(15, TimeUnit.MINUTES)) {
> 79: frame.dispose();
It must be called on EDT.
Suggestion:
SwingUtilities.invokeAndWait(() -> frame.dispose());
test/jdk/java/awt/Window/WindowIconUpdateOnDPIChanging/WindowIconUpdateOnDPIChangingTest.java line 98:
> 96: frame.getContentPane().add(createInstrumentsPane(), BorderLayout.CENTER);
> 97: frame.getContentPane().add(createControlPanel(), BorderLayout.SOUTH);
> 98: frame.setIconImages(IntStream.rangeClosed(16, 32).mapToObj(size -> createIcon(size)).toList());
In fact, I liked the version with method reference better even though the line is longer.
But I still suggest wrapping the line at each dot to make it clearer what operations are performed on the stream.
Suggestion:
frame.setIconImages(IntStream.rangeClosed(16, 32)
.mapToObj(size -> createIcon(size))
.toList());
It fits into 80 column limit. If it's replaced with method reference as it was before, it doesn't fit but I don't see it as big problem.
Alternatively, you can wrap the start of the stream too:
Suggestion:
frame.setIconImages(
IntStream.rangeClosed(16, 32)
.mapToObj(WindowIconUpdateOnDPIChangingTest::createIcon)
.toList());
The line with method reference takes 82 columns, I'm sure it's acceptable.
-------------
PR: https://git.openjdk.java.net/jdk/pull/6180
More information about the client-libs-dev
mailing list