From 2e222bcdeafcddd7bb23d417ead016a34c25af4d Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Fri, 18 Feb 2022 22:24:36 +0100 Subject: [PATCH] Native window decorations (Windows 10/11 only): fixed rendering artifacts on HiDPI screens when dragging window partly offscreen and back into screen bounds (issue #477) --- CHANGELOG.md | 3 +++ .../FlatWindowsNativeWindowBorder.java | 27 +++++++++++++++++++ .../src/main/cpp/FlatWndProc.cpp | 22 +++++++++++++++ .../src/main/cpp/FlatWndProc.h | 2 ++ 4 files changed, 54 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d94ecd82..eb3d1d07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ FlatLaf Change Log ## 2.1-SNAPSHOT +- Native window decorations (Windows 10/11 only): Fixed rendering artifacts on + HiDPI screens when dragging window partly offscreen and back into screen + bounds. (issue #477) - Repaint component when setting client property `JComponent.outline` (issue #480). diff --git a/flatlaf-natives/flatlaf-natives-jna/src/main/java/com/formdev/flatlaf/natives/jna/windows/FlatWindowsNativeWindowBorder.java b/flatlaf-natives/flatlaf-natives-jna/src/main/java/com/formdev/flatlaf/natives/jna/windows/FlatWindowsNativeWindowBorder.java index 5bc8bf45..ba23a195 100644 --- a/flatlaf-natives/flatlaf-natives-jna/src/main/java/com/formdev/flatlaf/natives/jna/windows/FlatWindowsNativeWindowBorder.java +++ b/flatlaf-natives/flatlaf-natives-jna/src/main/java/com/formdev/flatlaf/natives/jna/windows/FlatWindowsNativeWindowBorder.java @@ -288,6 +288,7 @@ public class FlatWindowsNativeWindowBorder private static final int GWLP_WNDPROC = -4; private static final int + WM_MOVE = 0x0003, WM_ERASEBKGND = 0x0014, WM_NCCALCSIZE = 0x0083, WM_NCHITTEST = 0x0084, @@ -301,6 +302,10 @@ public class FlatWindowsNativeWindowBorder WM_LBUTTONDOWN = 0x0201, WM_LBUTTONUP = 0x0202, + WM_MOVING = 0x0216, + WM_ENTERSIZEMOVE = 0x0231, + WM_EXITSIZEMOVE = 0x0232, + WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320; // WM_SIZE wParam @@ -341,6 +346,8 @@ public class FlatWindowsNativeWindowBorder private final LONG_PTR defaultWndProc; private int wmSizeWParam = -1; private HBRUSH background; + private boolean isMovingOrSizing; + private boolean isMoving; // Swing coordinates/values may be scaled on a HiDPI screen private int titleBarHeight; @@ -477,7 +484,27 @@ public class FlatWindowsNativeWindowBorder wParam = new WPARAM( wmSizeWParam ); break; + case WM_ENTERSIZEMOVE: + isMovingOrSizing = true; + break; + + case WM_EXITSIZEMOVE: + isMovingOrSizing = isMoving = false; + break; + + case WM_MOVE: + case WM_MOVING: + if( isMovingOrSizing ) + isMoving = true; + break; + case WM_ERASEBKGND: + // do not erase background while the user is moving the window, + // otherwise there may be rendering artifacts on HiDPI screens with Java 9+ + // when dragging the window partly offscreen and back into the screen bounds + if( isMoving ) + return new LRESULT( 0 ); + return WmEraseBkgnd( hwnd, uMsg, wParam, lParam ); case WM_DESTROY: diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.cpp b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.cpp index 38d4550d..b2f72ce1 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.cpp +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.cpp @@ -88,6 +88,8 @@ FlatWndProc::FlatWndProc() { defaultWndProc = NULL; wmSizeWParam = -1; background = NULL; + isMovingOrSizing = false; + isMoving = false; } HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) { @@ -250,7 +252,27 @@ LRESULT CALLBACK FlatWndProc::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, L wParam = wmSizeWParam; break; + case WM_ENTERSIZEMOVE: + isMovingOrSizing = true; + break; + + case WM_EXITSIZEMOVE: + isMovingOrSizing = isMoving = false; + break; + + case WM_MOVE: + case WM_MOVING: + if( isMovingOrSizing ) + isMoving = true; + break; + case WM_ERASEBKGND: + // do not erase background while the user is moving the window, + // otherwise there may be rendering artifacts on HiDPI screens with Java 9+ + // when dragging the window partly offscreen and back into the screen bounds + if( isMoving ) + return FALSE; + return WmEraseBkgnd( hwnd, uMsg, wParam, lParam ); case WM_DESTROY: diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.h b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.h index 646f5a57..768b7779 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.h +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.h @@ -43,6 +43,8 @@ private: WNDPROC defaultWndProc; int wmSizeWParam; HBRUSH background; + bool isMovingOrSizing; + bool isMoving; FlatWndProc(); static void initIDs( JNIEnv *env, jobject obj );