JDK-8150176 : [hidpi] wrong resolution variant of multi-res. image is used for TrayIcon
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-02-18
  • Updated: 2016-10-13
  • Resolved: 2016-09-15
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.
JDK 9
9 b140Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
Please compile/run the following code on HiDPI machine (or use sun.java2d.uiScale option):

import java.awt.*;
import java.awt.image.*;

public class TrayIconTest {

    private static BufferedImage generateImage(int w, int h, int scale, Color c) {

        int x = w * scale, y = h * scale;
        BufferedImage img = new BufferedImage(x, y, BufferedImage.TYPE_INT_RGB);
        Graphics g = img.getGraphics();
        g.setColor(c);
        g.fillRect(0, 0, x, y);
        g.setColor(Color.WHITE);
        g.fillRect(x / 3, y / 3, x / 3, y / 3);
        return img;
    }

    private static BaseMultiResolutionImage createIcon(int w, int h) {
        return new BaseMultiResolutionImage(
                new BufferedImage[]{generateImage(w, h, 1, Color.RED),
                                    generateImage(w, h, 2, Color.GREEN)});
    }
    
    public static void main(String[] args) throws Exception {
        
        if (!SystemTray.isSupported()) {
            System.err.println("tray is not supported");
            return;
        }
        
        SystemTray tray = SystemTray.getSystemTray();
        Dimension d = tray.getTrayIconSize();
        System.out.println("icon size: " + d.width + "x" + d.height);

        tray.add(new TrayIcon(createIcon(d.width, d.height)));
    }
}

expected: high-resolution ("green") icon will apear in the tray. in fact - the "red" one appears.

Win 8 + HiDPI, JDK9 b106
Comments
WTrayIconPeer uses fixed sizes TRAY_ICON_WIDTH/HEIGHT for image icon or the image size if isImageAutoSize is set. In case of the MultiResolutionImage the image size is just base image size. To make the WTrayIconPeer use high-resolution icons it is necessary to get a transform from a graphics configuration (in case of system tray icon it is probably a graphics configuration from the default screen device), scale the buffered image sizes and set the transform to the buffered image graphics. In this case the high-resolution variant will be retrieved from the multi-resolution image and drawn to the scaled buffered image. The WTrayIconPeer.setNativeIcon() method should be checked that it draws the icon with the initially requested size (not twice bigger). If the result icon is twice bigger it is necessary to update the setNativeIcon() method that the set icon is used as high-resolution image.
26-05-2016

Height and width of the TrayIcon dimensions for Windows are hardcoded with the value 16 in sun.awt.windows.WTrayIconPeer. This value is also referenced from sun.awt.windows.WSystemTrayPeer#getTrayIconSize(). sun.awt.windows.WTrayIconPeer#updateNativeImage() uses these hardcoded dimensions when TrayIcon#isImageAutoSize() is true to create a new BufferedImage with those dimensions. Doesn't seem to be quite right. :-/ Once this is fixed, I'd very much appreciate a back port to Java8 (as always). Thanks.
06-05-2016

Yes, thanks. After setting auto-size for iconMRI the situation is as follows: 1. Win. 8 + HiDPI - reproducible as well 2. Linux 15.04 + HiDPI + Unity - as it was mentioned above, cannot see the icons at all (bug?) (please disregard the previous version of the comment - it was for another test case)
01-03-2016

By default the trayIcon image should not scale(it should be used as is and cropped if necessar). It should be scaled only if setImageAutoSize is set to true. On macosx setImageAutoSize does not help(this is a bug), can you check this flag on win/lin+hidpi?
26-02-2016

please remove "@ignore" tag from test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java after the bug fix
26-02-2016

one more question - should "GDK_SCALE" or "sun.java2d.uiScale" options affect the output of getTrayIconSize()? (in fact, they do not for now)
18-02-2016

even in case tray.add(new TrayIcon(createIcon(d.width / 2, d.height / 2))); the "red" half-size icon appears, so the reason is not "the base one fits better"
18-02-2016

when trying to run on Ubuntu 14.04 Linux (Unity) with -Dsun.java2d.uiScale=2 or GDK_SCALE=2, can see a quarter of the "red" icon instead of the entire "green" for Ubuntu 15.04 don't see the icon at all (but can see output: "icon size: 24x24") - that may be a separate issue.
18-02-2016

for OS X 10.10 works as expected - the icon is green (b104)
18-02-2016