JRE-427 HighDPI Scaling not on all screens
diff --git a/src/share/classes/sun/java2d/SunGraphicsEnvironment.java b/src/share/classes/sun/java2d/SunGraphicsEnvironment.java
index 9f29b02..84ce425 100644
--- a/src/share/classes/sun/java2d/SunGraphicsEnvironment.java
+++ b/src/share/classes/sun/java2d/SunGraphicsEnvironment.java
@@ -61,6 +61,7 @@
 import sun.awt.DisplayChangedListener;
 import sun.awt.FontConfiguration;
 import sun.awt.SunDisplayChanger;
+import sun.awt.Win32GraphicsDevice;
 import sun.font.CompositeFontDescriptor;
 import sun.font.Font2D;
 import sun.font.FontManager;
@@ -377,15 +378,29 @@
         GraphicsEnvironment env = (ge == null ? getLocalGraphicsEnvironment() : ge);
 
         if (!GraphicsEnvironment.isHeadless()) {
+            boolean fractionalScaleEnabled = "true".equals(AccessController.doPrivileged(
+                    new GetPropertyAction("sun.java2d.uiFractScale.enabled", "false")));
+            boolean fractionalScaleOn = false;
             for (GraphicsDevice d : env.getScreenDevices()) {
-                if (d.getDefaultConfiguration().getDefaultTransform().getScaleX() > 1 ||
-                    d.getDefaultConfiguration().getDefaultTransform().getScaleY() > 1)
-                {
-                    return uiScaleOn = true;
+                double scaleX = d.getDefaultConfiguration().getDefaultTransform().getScaleX();
+                double scaleY = d.getDefaultConfiguration().getDefaultTransform().getScaleY();
+                if (scaleX != Math.floor(scaleX) || scaleY != Math.floor(scaleY)) {
+                    fractionalScaleOn = true;
+                    if (!fractionalScaleEnabled) break;
+                }
+                if (scaleX > 1 || scaleY > 1) {
+                    uiScaleOn = true;
+                }
+            }
+            if (!fractionalScaleEnabled && fractionalScaleOn) {
+                // Fallback to un-scaled behavior
+                uiScaleOn = false;
+                for (GraphicsDevice d : env.getScreenDevices()) {
+                    ((Win32GraphicsDevice)d).resetScaleFactors();
                 }
             }
         }
-        return uiScaleOn = false;
+        return uiScaleOn;
     }
 
     public static double getDebugScale() {
diff --git a/src/windows/classes/sun/awt/Win32GraphicsDevice.java b/src/windows/classes/sun/awt/Win32GraphicsDevice.java
index 466bb07..110dd4b 100644
--- a/src/windows/classes/sun/awt/Win32GraphicsDevice.java
+++ b/src/windows/classes/sun/awt/Win32GraphicsDevice.java
@@ -106,7 +106,7 @@
     private static native void initIDs();
 
     native void initDevice(int screen);
-    native void initNativeScale(int screen, boolean fractionalScaleEnabled);
+    native void initNativeScale(int screen);
     native void setNativeScale(int screen, float scaleX, float scaleY);
     native float getNativeScaleX(int screen);
     native float getNativeScaleY(int screen);
@@ -150,6 +150,13 @@
         return scaleY;
     }
 
+    /**
+     * Temp, until fractional scale is supported. Don't use this method!
+     */
+    public void resetScaleFactors() {
+        setNativeScale(screen, scaleX = 1f, scaleY = 1f);
+    }
+
     private void initScaleFactors() {
         if (SunGraphicsEnvironment.isUIScaleEnabled()) {
             if (debugScaleX > 0 && debugScaleY > 0) {
@@ -157,9 +164,7 @@
                 scaleY = debugScaleY;
                 setNativeScale(screen, scaleX, scaleY);
             } else {
-                boolean fScaleEnabled = "true".equals(AccessController.doPrivileged(
-                        new GetPropertyAction("sun.java2d.uiFractScale.enabled", "false")));
-                initNativeScale(screen, fScaleEnabled);
+                initNativeScale(screen);
                 scaleX = getNativeScaleX(screen);
                 scaleY = getNativeScaleY(screen);
             }
diff --git a/src/windows/native/sun/windows/awt.h b/src/windows/native/sun/windows/awt.h
index 9191035..7f78497 100644
--- a/src/windows/native/sun/windows/awt.h
+++ b/src/windows/native/sun/windows/awt.h
@@ -52,6 +52,26 @@
 } PROCESS_DPI_AWARENESS;
 #endif
 
+#ifndef _WIN32_WINNT_WIN10
+typedef enum _DPI_AWARENESS {
+    DPI_AWARENESS_INVALID            = -1,
+    DPI_AWARENESS_UNAWARE            = 0,
+    DPI_AWARENESS_SYSTEM_AWARE       = 1,
+    DPI_AWARENESS_PER_MONITOR_AWARE  = 2
+} DPI_AWARENESS;
+
+DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
+
+#define DPI_AWARENESS_CONTEXT_UNAWARE              ((DPI_AWARENESS_CONTEXT)-1)
+#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE         ((DPI_AWARENESS_CONTEXT)-2)
+#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE    ((DPI_AWARENESS_CONTEXT)-3)
+#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
+
+typedef DPI_AWARENESS_CONTEXT(WINAPI GetThreadDpiAwarenessContextFunc)(void);
+typedef DPI_AWARENESS_CONTEXT(WINAPI SetThreadDpiAwarenessContextFunc)(DPI_AWARENESS_CONTEXT);
+typedef BOOL(AreDpiAwarenessContextsEqualFunc)(DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT);
+#endif
+
 // val >= 0 todo [tav] until switch to VS'12
 #define round(val) floor(val + 0.5)
 
diff --git a/src/windows/native/sun/windows/awt_Toolkit.cpp b/src/windows/native/sun/windows/awt_Toolkit.cpp
index 987403f..075045d 100644
--- a/src/windows/native/sun/windows/awt_Toolkit.cpp
+++ b/src/windows/native/sun/windows/awt_Toolkit.cpp
@@ -127,6 +127,10 @@
 
 #define IDT_AWT_MOUSECHECK 0x101
 
+GetThreadDpiAwarenessContextFunc* AwtToolkit::lpGetThreadDpiAwarenessContext = NULL;
+SetThreadDpiAwarenessContextFunc* AwtToolkit::lpSetThreadDpiAwarenessContext = NULL;
+AreDpiAwarenessContextsEqualFunc* AwtToolkit::lpAreDpiAwarenessContextsEqual = NULL;
+
 static LPCTSTR szAwtToolkitClassName = TEXT("SunAwtToolkit");
 
 static const int MOUSE_BUTTONS_WINDOWS_SUPPORTED = 5; //three standard buttons + XBUTTON1 + XBUTTON2.
@@ -503,9 +507,33 @@
 
     awt_dnd_initialize();
 
+    HMODULE hLibUser32Dll = JDK_LoadSystemLibrary("User32.dll");
+    if (hLibUser32Dll != NULL) {
+        lpGetThreadDpiAwarenessContext =
+                (GetThreadDpiAwarenessContextFunc*)GetProcAddress(hLibUser32Dll, "GetThreadDpiAwarenessContext");
+        lpSetThreadDpiAwarenessContext =
+                (SetThreadDpiAwarenessContextFunc*)GetProcAddress(hLibUser32Dll, "SetThreadDpiAwarenessContext");
+        lpAreDpiAwarenessContextsEqual =
+                (AreDpiAwarenessContextsEqualFunc*)GetProcAddress(hLibUser32Dll, "AreDpiAwarenessContextsEqual");
+        ::FreeLibrary(hLibUser32Dll);
+    }
+
     return TRUE;
 }
 
+void AwtToolkit::_UpdateToolkitDpiAwarenessContext(void* p = NULL)
+{
+    static DPI_AWARENESS_CONTEXT context = NULL;
+    if (p != NULL) context = static_cast<DPI_AWARENESS_CONTEXT>(p); // cache the last context
+
+    if (context != NULL &&
+        lpAreDpiAwarenessContextsEqual != NULL &&
+        !lpAreDpiAwarenessContextsEqual(GetToolkitDpiAwarenessContext(), context))
+    {
+        SetToolkitDpiAwarenessContext(context);
+    }
+}
+
 BOOL AwtToolkit::Dispose() {
     DTRACE_PRINTLN("In AwtToolkit::Dispose()");
 
diff --git a/src/windows/native/sun/windows/awt_Toolkit.h b/src/windows/native/sun/windows/awt_Toolkit.h
index 3782aac..aba1a20 100644
--- a/src/windows/native/sun/windows/awt_Toolkit.h
+++ b/src/windows/native/sun/windows/awt_Toolkit.h
@@ -384,6 +384,25 @@
     static BOOL CALLBACK CommonPeekMessageFunc(MSG& msg);
     static BOOL activateKeyboardLayout(HKL hkl);
 
+    static INLINE DPI_AWARENESS_CONTEXT GetToolkitDpiAwarenessContext()
+    {
+        return lpGetThreadDpiAwarenessContext != NULL ? lpGetThreadDpiAwarenessContext() : NULL;
+    }
+
+    static INLINE DPI_AWARENESS_CONTEXT SetToolkitDpiAwarenessContext(DPI_AWARENESS_CONTEXT context)
+    {
+        return lpSetThreadDpiAwarenessContext != NULL ? lpSetThreadDpiAwarenessContext(context) : NULL;
+    }
+
+    static INLINE void UpdateToolkitDpiAwarenessContext(DPI_AWARENESS_CONTEXT context = NULL)
+    {
+        if (AwtToolkit::IsMainThread()) {
+            _UpdateToolkitDpiAwarenessContext(context);
+        } else {
+            AwtToolkit::GetInstance().InvokeFunctionLater(_UpdateToolkitDpiAwarenessContext, static_cast<void*>(context));
+        }
+    }
+
     HANDLE m_waitEvent;
     DWORD eventNumber;
 private:
@@ -430,6 +449,11 @@
 
     CriticalSection m_Sync;
 
+    static GetThreadDpiAwarenessContextFunc *lpGetThreadDpiAwarenessContext;
+    static SetThreadDpiAwarenessContextFunc *lpSetThreadDpiAwarenessContext;
+    static AreDpiAwarenessContextsEqualFunc *lpAreDpiAwarenessContextsEqual;
+    static void _UpdateToolkitDpiAwarenessContext(void*);
+
 /* track display changes - used by palette-updating code.
    This is a workaround for a windows bug that prevents
    WM_PALETTECHANGED event from occurring immediately after
diff --git a/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp b/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp
index e59b323..f3e90e0 100644
--- a/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp
+++ b/src/windows/native/sun/windows/awt_Win32GraphicsDevice.cpp
@@ -696,7 +696,7 @@
     pt->y = device == NULL ? pt->y : device->ScaleDownDY(pt->y);
 }
 
-void AwtWin32GraphicsDevice::InitDesktopScales(bool fractionalScaleEnabled)
+void AwtWin32GraphicsDevice::InitDesktopScales()
 {
     unsigned x = 0;
     unsigned y = 0;
@@ -752,8 +752,7 @@
 
     float scaleX = dpiX / 96;
     float scaleY = dpiY / 96;
-    bool isFractScale = (scaleX != (int)scaleX || scaleY != (int)scaleY);
-    if (scaleX > 0 && scaleY > 0 && (fractionalScaleEnabled || !isFractScale)) {
+    if (scaleX > 0 && scaleY > 0) {
         SetScale(scaleX, scaleY);
     }
 }
@@ -1534,12 +1533,12 @@
 */
 JNIEXPORT void JNICALL
 Java_sun_awt_Win32GraphicsDevice_initNativeScale
-(JNIEnv *env, jobject thisPtr, jint screen, jboolean fractionalScaleEnabled)
+(JNIEnv *env, jobject thisPtr, jint screen)
 {
     Devices::InstanceAccess devices;
     AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
 
     if (device != NULL) {
-        device->InitDesktopScales((bool)fractionalScaleEnabled);
+        device->InitDesktopScales();
     }
 }
\ No newline at end of file
diff --git a/src/windows/native/sun/windows/awt_Win32GraphicsDevice.h b/src/windows/native/sun/windows/awt_Win32GraphicsDevice.h
index 335a20e..b7bd33f 100644
--- a/src/windows/native/sun/windows/awt_Win32GraphicsDevice.h
+++ b/src/windows/native/sun/windows/awt_Win32GraphicsDevice.h
@@ -74,7 +74,7 @@
     void                    Release();
     void                    DisableOffscreenAcceleration();
     void                    Invalidate(JNIEnv *env);
-    void                    InitDesktopScales(bool fractionalScaleEnabled);
+    void                    InitDesktopScales();
     void                    SetScale(float scaleX, float scaleY);
     float                   GetScaleX();
     float                   GetScaleY();
diff --git a/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp b/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp
index 287f684..81a367d 100644
--- a/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp
+++ b/src/windows/native/sun/windows/awt_Win32GraphicsEnv.cpp
@@ -94,7 +94,19 @@
     }
 
     if (lpSetProcessDpiAwareness != NULL) {
+        // [tav] has no effect when called repeatedly, therefore the thread DPI_AWARENESS_CONTEXT is set
         lpSetProcessDpiAwareness(level);
+        switch (level) {
+            case PROCESS_DPI_UNAWARE:
+                AwtToolkit::UpdateToolkitDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
+                break;
+            case PROCESS_SYSTEM_DPI_AWARE:
+                AwtToolkit::UpdateToolkitDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
+                break;
+            case PROCESS_PER_MONITOR_DPI_AWARE:
+                AwtToolkit::UpdateToolkitDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
+                break;
+        }
     }
 }
 
diff --git a/src/windows/native/sun/windows/awt_Window.cpp b/src/windows/native/sun/windows/awt_Window.cpp
index 152194a..810ac30 100644
--- a/src/windows/native/sun/windows/awt_Window.cpp
+++ b/src/windows/native/sun/windows/awt_Window.cpp
@@ -487,6 +487,12 @@
 
     TweakStyle(windowStyle, windowExStyle);
 
+    // [tav] It has been noticed experimentally that the thread DPI_AWARENESS_CONTEXT is not passed
+    // to a new toplevel unless is set at processing of the same message which creates HWND.
+    // That is, the thread DPI_AWARENESS_CONTEXT may vary depending on the foreground toplevel.
+    // To make every toplevel inherit the same context, it's updated right before HWND creation.
+    AwtToolkit::UpdateToolkitDpiAwarenessContext();
+
     AwtCanvas::CreateHWnd(env, title,
             windowStyle,
             windowExStyle,