Modify

Opened 5 years ago

Closed 5 years ago

#16805 closed enhancement (fixed)

Use scalable hi-res desktop icon

Reported by: anonymous Owned by: team
Priority: normal Milestone: 18.10
Component: Core Webstart Version: latest
Keywords: icon hidpi windows javabug Cc: stoecker

Description (last modified by Klumbumbus)

I put IntelliJ's icon next to JOSM's for comparison.

Attachments (1)

JOSM icon on desktop.png (73.0 KB ) - added by anonymous 5 years ago.

Download all attachments as: .zip

Change History (19)

by anonymous, 5 years ago

Attachment: JOSM icon on desktop.png added

comment:1 by anonymous, 5 years ago

Component: CoreInstaller Windows

Oh, I forgot to mention, the screenshot is from Windows 10 1803.

comment:2 by Klumbumbus, 5 years ago

Description: modified (diff)

comment:3 by Klumbumbus, 5 years ago

Keywords: hidpi added

comment:4 by Don-vip, 5 years ago

Component: Installer WindowsCore Webstart
Keywords: windows javabug added

We actually use a much larger file in josm.jnlp:

<icon href="https://josm.openstreetmap.de/logo.png"/> 

But Oracle WebStart scales it down to a very poor resolution icon (32x32 pixels).

comment:5 by anonymous, 5 years ago

Isn't the width and height attributes working? https://coderanch.com/t/200635/java/desktop-icon

in reply to:  5 comment:6 by Don-vip, 5 years ago

Replying to anonyme:

Isn't the width and height attributes working? https://coderanch.com/t/200635/java/desktop-icon

We currently don't set them, maybe we should. I thought the JNLP client was smart about this. Maybe not according to JNLP specification (JSR 56):

icon element: The icon can be used by a JNLP Client to identify the application to the user.

The optional width and height attributes can be used to indicate the resolution of the images. Both are measured in pixels.

The optional depth attribute can be used to describe the color depth of the image.

The optional kind attribute can be used to indicate the use of the icon, such as default, selected, disabled, rollover, splash, and shortcut.

The optional size attribute can be used to specify the download size of the icon in bytes.

The image file can be either GIF or JPEG format, or other (possibly platform dependant) formats. The JNLP Client may assume that a typical JNLP file will have at least an icon in GIF or JPEG format of 32x32 pixels in 256 colors of the default kind.

comment:7 by Don-vip, 5 years ago

In 14297/josm:

see #16805 - specify webstart icon size

comment:8 by Don-vip, 5 years ago

Cc: stoecker added

Dirk, I don't have access to JOSM server this week-end. Can you please report the above modification to jnlp files?

comment:9 by stoecker, 5 years ago

Done.

comment:10 by anonymous, 5 years ago

How can I test it? JOSM updated itself, but the icon remained the same.

comment:11 by Klumbumbus, 5 years ago

I didn't test but this should work:

comment:12 by anonymous, 5 years ago

Thanks Klumbumbus for the instructions. I did it without luck.

Also the

<icon href="https://josm.openstreetmap.de/logo.png" kind="shortcut" width="256" height="258"/>

not working at all.

Last edited 5 years ago by Don-vip (previous) (diff)

comment:13 by Don-vip, 5 years ago

Indeed it does not work yet. We should start by making the icon square (256x256 pixels).

I found this comment where an Oracle employee says javaws can scale icons to 128x128.

Last edited 5 years ago by Don-vip (previous) (diff)

comment:14 by anonymous, 5 years ago

I tried with 128x128 .ico, it doesn't work either.

comment:15 by Don-vip, 5 years ago

Some useful pieces of Java WebStart 8u181 decompiled code:

public final class WinPlatform
  extends Platform
{
  private static final int[] DEFAULT_SIZES = { 32, 16, 48, 64 };
  public int[] getIconSizes()
  {
    return DEFAULT_SIZES;
  }
  
  public int getSystemShortcutIconSize(boolean paramBoolean)
  {
    if (paramBoolean)
    {
      int i = getDesktopIconSize();
      if ((i >= 16) && (i <= 64)) {
        return i;
      }
      return isPlatformWindowsVista() ? 48 : 32;
    }
    return 16;
  }

  public boolean isPlatformIconType(String paramString)
  {
    return paramString.toLowerCase().endsWith(".ico");
  }

  public native boolean isPlatformWindowsVista();
  public native boolean isPlatformWindows8orLater();
}
public class IconDesc
  implements XMLable
{
  private URL _location;
  private String _version;
  private String _locationString;
  private int _height;
  private int _width;
  private int _depth;
  private int _kind;
  private String _suffix;
  public static final int ICON_KIND_DEFAULT = 0;
  public static final int ICON_KIND_SELECTED = 1;
  public static final int ICON_KIND_DISABLED = 2;
  public static final int ICON_KIND_ROLLOVER = 3;
  public static final int ICON_KIND_SPLASH = 4;
  public static final int ICON_KIND_SHORTCUT = 5;
  private static final String[] kinds = { "default", "selected", "disabled", "rollover", "splash", "shortcut" };
  
  public IconDesc(URL paramURL, String paramString, int paramInt1, int paramInt2, int paramInt3, int paramInt4)
  {
    this._location = paramURL;
    this._suffix = "";
    if (this._location != null)
    {
      this._locationString = this._location.toExternalForm();
      int i = this._locationString.lastIndexOf(".");
      if (i > 0) {
        this._suffix = this._locationString.substring(i);
      }
    }
    this._height = paramInt1;
    this._width = paramInt2;
    this._depth = paramInt3;
    this._kind = paramInt4;
    this._version = paramString;
  }
public class InformationDesc
  implements XMLable
{
  private String _title;
  private String _vendor;
  private URL _home;
  private String[] _descriptions;
  private IconDesc[] _icons;
  private ShortcutDesc _shortcutHints;
  private AssociationDesc[] _associations;
  private RContentDesc[] _relatedContent;
  private boolean _supportOfflineOperation;

  public IconDesc[] getIcons()
  {
    return this._icons;
  }

  public IconDesc getIconLocation(int paramInt1, int paramInt2)
  {
    if (this._icons == null) {
      return null;
    }
    Object localObject = null;
    long l1 = 0L;
    for (int i = 0; i < this._icons.length; i++)
    {
      IconDesc localIconDesc = this._icons[i];
      int j = (paramInt2 == 5) || (!localIconDesc.getSuffix().equalsIgnoreCase(".ico")) ? 1 : 0;
      if ((localIconDesc.getKind() == paramInt2) && (j != 0))
      {
        if ((localIconDesc.getHeight() == paramInt1) && (localIconDesc.getWidth() == paramInt1)) {
          return localIconDesc;
        }
        if ((localIconDesc.getHeight() == 0) && (localIconDesc.getWidth() == 0))
        {
          if (localObject == null) {
            localObject = localIconDesc;
          }
        }
        else
        {
          int k = localIconDesc.getHeight() + localIconDesc.getWidth() - 2 * paramInt1;
          long l2 = Math.abs(k);
          if ((l1 == 0L) || (l2 < l1))
          {
            l1 = l2;
            localObject = localIconDesc;
          }
          else if ((l2 == l1) && (k > 0))
          {
            localObject = localIconDesc;
          }
        }
      }
    }
    return (IconDesc)localObject;
  }
}
public class IconUtil
{
  public static String getIconPath(LaunchDesc paramLaunchDesc, boolean paramBoolean)
  {
    return getIconPath(paramLaunchDesc);
  }
  
  public static String getIconPath(LaunchDesc paramLaunchDesc)
  {
    ArrayList localArrayList = new ArrayList();
    int[] arrayOfInt1 = Platform.get().getIconSizes();
    Integer localInteger1 = new Integer(Platform.get().getSystemShortcutIconSize(true));
    Integer localInteger2 = new Integer(Platform.get().getSystemShortcutIconSize(false));
    for (Integer localInteger3 = 0; localInteger3 < arrayOfInt1.length; localInteger3++)
    {
      localInteger4 = new Integer(arrayOfInt1[localInteger3]);
      if (!localArrayList.contains(localInteger4)) {
        localArrayList.add(localInteger4);
      }
    }
    if (!localArrayList.contains(localInteger1)) {
      localArrayList.add(localInteger1);
    }
    if (!localArrayList.contains(localInteger2)) {
      localArrayList.add(localInteger2);
    }
    localInteger3 = ((Integer)localArrayList.get(0)).intValue();
    Integer localInteger4 = localInteger3;
    Integer localInteger5 = localInteger3;
    int j;
    int i;
    for (int k = 0; k < localArrayList.size(); k++)
    {
      localInteger3 = ((Integer)localArrayList.get(k)).intValue();
      if (localInteger3 > localInteger5) {
        j = localInteger3;
      }
      if (localInteger3 < localInteger4) {
        i = localInteger3;
      }
    }
    Iterator localIterator = localArrayList.iterator();
    IconDesc[] arrayOfIconDesc = new IconDesc[localArrayList.size()];
    int[] arrayOfInt2 = new int[localArrayList.size()];
    int m = 0;
    while (localIterator.hasNext())
    {
      int n = ((Integer)localIterator.next()).intValue();
      if (n < i) {
        n = i;
      }
      if (n > j) {
        n = j;
      }
      localObject2 = paramLaunchDesc.getInformation().getIconLocation(n, 5);
      if (localObject2 == null) {
        localObject2 = paramLaunchDesc.getInformation().getIconLocation(n, 0);
      }
      if (localObject2 != null)
      {
        i1 = 0;
        for (int i2 = 0; (i2 < m) && (i1 == 0); i2++) {
          if (((IconDesc)localObject2).equals(arrayOfIconDesc[i2])) {
            i1 = 1;
          }
        }
        if (i1 == 0)
        {
          arrayOfIconDesc[m] = localObject2;
          i2 = ((IconDesc)localObject2).getWidth();
          int i3 = ((IconDesc)localObject2).getHeight();
          if ((i2 == i3) && (i2 >= i) && (i2 <= j)) {
            arrayOfInt2[m] = i2;
          } else {
            arrayOfInt2[m] = n;
          }
          m++;
        }
      }
    }
    Object localObject1 = null;
    Object localObject2 = new File[localArrayList.size()];
    for (int i1 = 0; i1 < m; i1++)
    {
      String str1 = null;
      Object localObject3 = null;
      try
      {
        Resource localResource = ResourceProvider.get().getResource(arrayOfIconDesc[i1].getLocation(), arrayOfIconDesc[i1].getVersion());
        Object localObject4 = localResource != null ? localResource.getDataFile() : null;
        if (localObject4 != null)
        {
          if (Platform.get().isPlatformIconType(arrayOfIconDesc[i1].getLocation().toString()))
          {
            str1 = ((File)localObject4).toString();
            localObject3 = localObject4;
          }
          else
          {
            String str2 = Platform.get().getPlatformIconType();
            str1 = ((File)localObject4).getPath() + "." + str2;
            localObject3 = new File(str1);
          }
          if (((File)localObject3).exists())
          {
            localObject1 = str1;
            return (String)localObject1;
          }
          if (localObject1 == null) {
            localObject1 = str1;
          }
          localObject2[i1] = localObject4;
        }
      }
      catch (IOException localIOException)
      {
        Trace.ignored(localIOException);
      }
    }
    if ((localObject1 != null) && (m > 0))
    {
      IconEncoder localIconEncoder = Platform.get().getIconEncoder();
      localIconEncoder.convert((File[])localObject2, arrayOfInt2, m, (String)localObject1); // <<<<<<<<
    }
    if ((localObject1 != null) && (new File((String)localObject1).exists())) {
      return (String)localObject1;
    }
    return null;
  }
  
  public static String getIconPath(URL paramURL, String paramString)
  {
    String str = null;
    File localFile2 = null;
    Object localObject;
    try
    {
      Resource localResource = ResourceProvider.get().getResource(paramURL, paramString);
      if (localResource != null) {
        localFile2 = localResource.getDataFile();
      }
      if (localFile2 != null)
      {
        File localFile1;
        if (Platform.get().isPlatformIconType(paramURL.toString()))
        {
          str = localFile2.toString();
          localFile1 = localFile2;
        }
        else
        {
          localObject = Platform.get().getPlatformIconType();
          str = localFile2.getPath() + "." + (String)localObject;
          localFile1 = new File(str);
        }
        if (localFile1.exists()) {
          return str;
        }
      }
    }
    catch (IOException localIOException)
    {
      Trace.ignored(localIOException);
    }
    if (str != null)
    {
      File[] arrayOfFile = { localFile2 };
      localObject = new int[] { 32 };
      int i = 1;
      IconEncoder localIconEncoder = Platform.get().getIconEncoder();
      localIconEncoder.convert(arrayOfFile, (int[])localObject, i, str); // <<<<<<<<
    }
    if ((str != null) && (new File(str).exists())) {
      return str;
    }
    return null;
  }
}
public class ApplicationIconGenerator
  extends Thread
{
  private File _index;
  private File _dir;
  private final String _key;
  private final LaunchDesc _ld;
  private Properties _props = new Properties();

  public void run()
  {
    if ((!this._dir.getParentFile().canWrite()) || ((this._dir.exists()) && (!this._dir.canWrite())) || ((this._index.exists()) && (!this._index.canWrite()))) {
      return;
    }
    try
    {
      this._dir.mkdirs();
    }
    catch (Throwable localThrowable1)
    {
      appIconError(localThrowable1);
    }
    try
    {
      this._index.createNewFile();
    }
    catch (Throwable localThrowable2)
    {
      appIconError(localThrowable2);
    }
    String str = IconUtil.getIconPath(this._ld); // <<<<<<<<
    if (str == null) {
      return;
    }
    try
    {
      addAppIconToCacheIndex(this._key, str);
    }
    catch (Throwable localThrowable3)
    {
      Trace.ignored(localThrowable3);
    }
  }
public class WinInstallHandler
  extends LocalInstallHandler
{
  private boolean handleInstall(LaunchDesc paramLaunchDesc, ShortcutDesc paramShortcutDesc, LocalApplicationProperties paramLocalApplicationProperties, String paramString, int paramInt)
  {
    String str1 = null;
    WinPlatform localWinPlatform = null;
    if ((Platform.get() instanceof WinPlatform))
    {
      localWinPlatform = (WinPlatform)Platform.get();
      str1 = localWinPlatform.getJavawsPathInCommonAppDir();
    }
    InformationDesc localInformationDesc = paramLaunchDesc.getInformation();
    String str3 = null;
    String str4 = getIconPath(paramLaunchDesc, true); // <<<<<<<<
    String str5 = getIconPath(paramLaunchDesc, false); // <<<<<<<<
    String str6 = str1 != null ? str1 : Platform.get().getSystemJavawsPath();
    String str7 = localInformationDesc.getDescription(0);
    String str8 = localInformationDesc.getDescription(3);
    String str9 = str8 == null ? str7 : str8;
    boolean bool = true;
    String str10 = paramLaunchDesc.getLocation() != null ? paramLaunchDesc.getLocation().toString() : null;
    String str11 = "-J-Djnlp.application.href=" + str10 + " ";
    int i = (!localInformationDesc.supportsOfflineOperation()) || (paramShortcutDesc == null) || (paramShortcutDesc.getOnline()) ? 1 : 0;
    String str12 = i != 0 ? "" : "-offline ";
    String str13 = "-localfile " + str12 + str11 + "\"" + paramString + "\"";
    if (str13.length() >= 255) {
      str13 = "-localfile " + str12 + "\"" + paramString + "\"";
    }
    String str2;
    int j;
    if (paramInt == 1)
    {
      str2 = getDesktopPath(paramLaunchDesc);
      str3 = getInstallName(paramLaunchDesc);
      if ((localWinPlatform != null) && (localWinPlatform.isPlatformWindows8orLater())) {
        str4 = copyIconFileForWindows8(str4);
      }
      j = installWrapper(str2, str3, str9, str6, str13, null, str4);
      // ...
    }
    else
    {
      File localFile1 = new File(getSubMenuPath(paramLaunchDesc));
      if ((localFile1.exists()) || (localFile1.mkdirs()))
      {
        str2 = getStartMenuPath(paramLaunchDesc);
        str3 = getInstallName(paramLaunchDesc);
        if ((localWinPlatform != null) && (localWinPlatform.isPlatformWindows8orLater())) {
          str5 = copyIconFileForWindows8(str5);
        }
        j = installWrapper(str2, str3, str9, str6, str13, null, str5);
        // ...
      }
      // ...
    }
    return bool;
  }

comment:16 by Don-vip, 5 years ago

In 14321/josm:

see #16805 - make logo square (256x256)

comment:17 by Don-vip, 5 years ago

In 14322/josm:

see #16805 - add 64x64 logo

comment:18 by Don-vip, 5 years ago

Milestone: 18.10
Resolution: fixed
Status: newclosed

It seems not possible to do better than 64x64 pixels with Oracle WebStart on Windows. We'll have to revisit the issue if we can maintain Java Web Start with AdoptOpenJDK & IcedTea-Web.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain team.
as The resolution will be set.
The resolution will be deleted. Next status will be 'reopened'.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.