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)

This commit is contained in:
Karl Tauber
2022-02-18 22:24:36 +01:00
parent 4174b065f3
commit 2e222bcdea
4 changed files with 54 additions and 0 deletions

View File

@@ -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).

View File

@@ -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:

View File

@@ -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:

View File

@@ -43,6 +43,8 @@ private:
WNDPROC defaultWndProc;
int wmSizeWParam;
HBRUSH background;
bool isMovingOrSizing;
bool isMoving;
FlatWndProc();
static void initIDs( JNIEnv *env, jobject obj );