JRE-580 [windows] low-res app icon on HiDPI displays

(cherry picked from commit b446cd4)
diff --git a/src/windows/classes/sun/awt/windows/WToolkit.java b/src/windows/classes/sun/awt/windows/WToolkit.java
index c6bfff0..33518f2 100644
--- a/src/windows/classes/sun/awt/windows/WToolkit.java
+++ b/src/windows/classes/sun/awt/windows/WToolkit.java
@@ -129,6 +129,12 @@
         {
             @Override
             public Void run() {
+                // By default, java.exe & awt.dll contains standard JDK icon resource.
+                // JBRE supports "jbre.win.app.icon.id" property which identifies
+                // the resource id of the icon packed into the executable launcher
+                // other than java.exe, e.g. idea.exe.
+                System.setProperty("jbre.win.app.icon.supported", "true");
+
                 String browserProp = System.getProperty("browser");
                 if (browserProp != null && browserProp.equals("sun.plugin")) {
                     disableCustomPalette();
diff --git a/src/windows/native/sun/windows/awt_Toolkit.cpp b/src/windows/native/sun/windows/awt_Toolkit.cpp
index afa0f6f..242c403 100644
--- a/src/windows/native/sun/windows/awt_Toolkit.cpp
+++ b/src/windows/native/sun/windows/awt_Toolkit.cpp
@@ -1629,9 +1629,55 @@
     return m_cmdIDs->Lookup(id);
 }
 
+bool AwtToolkit::GetIntegerProperty(LPTSTR prop, int& value)
+{
+    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+    if (!env) return false;
+
+    static jclass cInteger = env->FindClass("java/lang/Integer");
+    DASSERT(cInteger);
+    static jmethodID mGetInteger = env->GetStaticMethodID(cInteger, "getInteger", "(Ljava/lang/String;)Ljava/lang/Integer;");
+    DASSERT(mGetInteger);
+
+    jstring propStr = JNU_NewStringPlatform(env, prop);
+    jobject jInt = env->CallStaticObjectMethod(cInteger, mGetInteger, propStr);
+    env->DeleteLocalRef(propStr);
+    if (!jInt) return false;
+
+    static jmethodID mIntValue = env->GetMethodID(cInteger, "intValue", "()I");
+    DASSERT(mIntValue);
+
+    value = (int)env->CallIntMethod(jInt, mIntValue);
+    env->DeleteLocalRef(jInt);
+    if (safe_ExceptionOccurred(env)) return false;
+    return true;
+}
+
+static bool GetWinAppIconID(int& id)
+{
+    static CriticalSection lock;
+    CriticalSection::Lock l(lock);
+
+    static bool initialized = false;
+    static int* iconID;
+    if (!initialized) {
+        initialized = true;
+        int v;
+        if (AwtToolkit::GetIntegerProperty(TEXT("jbre.win.app.icon.id"), v)) iconID = new int(v);
+    }
+    if (!iconID) return false;
+    id = *iconID;
+    return true;
+}
+
 HICON AwtToolkit::GetAwtIcon()
 {
-    return ::LoadIcon(GetModuleHandle(), TEXT("AWT_ICON"));
+    int iconID;
+    if (GetWinAppIconID(iconID)) {
+        return ::LoadIcon(::GetModuleHandle(NULL), MAKEINTRESOURCE(iconID));
+    } else {
+        return ::LoadIcon(GetModuleHandle(), TEXT("AWT_ICON"));
+    }
 }
 
 HICON AwtToolkit::GetAwtIconSm()
@@ -1645,7 +1691,13 @@
 
     // Fixed 6364216: LoadImage() may leak memory
     if (defaultIconSm == NULL || smx != prevSmx || smy != prevSmy) {
-        defaultIconSm = (HICON)LoadImage(GetModuleHandle(), TEXT("AWT_ICON"), IMAGE_ICON, smx, smy, 0);
+        int iconID;
+        if (GetWinAppIconID(iconID)) {
+            // loads the best fitting resolution icon from the resource
+            defaultIconSm = ::LoadIcon(::GetModuleHandle(NULL), MAKEINTRESOURCE(iconID));
+        } else {
+            defaultIconSm = (HICON)LoadImage(GetModuleHandle(), TEXT("AWT_ICON"), IMAGE_ICON, smx, smy, 0);
+        }
         prevSmx = smx;
         prevSmy = smy;
     }
diff --git a/src/windows/native/sun/windows/awt_Toolkit.h b/src/windows/native/sun/windows/awt_Toolkit.h
index 13be45a..65ebca8 100644
--- a/src/windows/native/sun/windows/awt_Toolkit.h
+++ b/src/windows/native/sun/windows/awt_Toolkit.h
@@ -375,6 +375,8 @@
 
     static void SetBusy(BOOL busy);
 
+    static bool GetIntegerProperty(LPTSTR prop, int& value);
+
     /* Set and get the default input method Window handler. */
     INLINE void SetInputMethodWindow(HWND inputMethodHWnd) { m_inputMethodHWnd = inputMethodHWnd; }
     INLINE HWND GetInputMethodWindow() { return m_inputMethodHWnd; }