Opened 6 years ago
Closed 6 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 )
Attachments (1)
Change History (19)
by , 6 years ago
Attachment: | JOSM icon on desktop.png added |
---|
comment:1 by , 6 years ago
Component: | Core → Installer Windows |
---|
comment:2 by , 6 years ago
Description: | modified (diff) |
---|
comment:3 by , 6 years ago
Keywords: | hidpi added |
---|
comment:4 by , 6 years ago
Component: | Installer Windows → Core 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).
follow-up: 6 comment:5 by , 6 years ago
Isn't the width and height attributes working? https://coderanch.com/t/200635/java/desktop-icon
comment:6 by , 6 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:8 by , 6 years ago
Cc: | added |
---|
Dirk, I don't have access to JOSM server this week-end. Can you please report the above modification to jnlp files?
comment:11 by , 6 years ago
I didn't test but this should work:
- Download the newest latest.jnlp from https://josm.openstreetmap.de/wiki or https://josm.openstreetmap.de/wiki/Download
- Clear the Java cache https://www.java.com/en/download/help/plugin_cache.xml (Your JOSM settings will not be deleted.)
- Execute the new jnlp.
comment:12 by , 6 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.
comment:13 by , 6 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.
comment:15 by , 6 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:18 by , 6 years ago
Milestone: | → 18.10 |
---|---|
Resolution: | → fixed |
Status: | new → closed |
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.
Oh, I forgot to mention, the screenshot is from Windows 10 1803.