Native window decorations: fixed broken maximizing window (under special conditions) when restoring frame state at startup (issue #283)

This commit is contained in:
Karl Tauber
2021-05-13 12:10:11 +02:00
parent 359eedf773
commit eea341fb33
7 changed files with 338 additions and 34 deletions

View File

@@ -292,6 +292,11 @@ public class FlatWindowsNativeWindowBorder
WM_NCRBUTTONUP = 0x00A5,
WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320;
// WM_SIZE wParam
private static final int
SIZE_MINIMIZED = 1,
SIZE_MAXIMIZED = 2;
// WM_NCHITTEST mouse position codes
private static final int
HTCLIENT = 1,
@@ -320,6 +325,7 @@ public class FlatWindowsNativeWindowBorder
private Window window;
private final HWND hwnd;
private final BaseTSD.LONG_PTR defaultWndProc;
private int wmSizeWParam = -1;
private int titleBarHeight;
private Rectangle[] hitTestSpots;
@@ -338,16 +344,7 @@ public class FlatWindowsNativeWindowBorder
defaultWndProc = User32Ex.INSTANCE.SetWindowLong( hwnd, GWLP_WNDPROC, this );
// remove the OS window title bar
if( window instanceof JFrame && ((JFrame)window).getExtendedState() != 0 ) {
// In case that the frame should be maximized or minimized immediately
// when showing, then it is necessary to defer ::SetWindowPos() invocation.
// Otherwise the frame will not be maximized or minimized.
// This occurs only if frame.pack() was no invoked.
EventQueue.invokeLater( () -> {
updateFrame();
});
} else
updateFrame();
updateFrame( (window instanceof JFrame) ? ((JFrame)window).getExtendedState() : 0 );
}
void uninstall() {
@@ -358,16 +355,31 @@ public class FlatWindowsNativeWindowBorder
User32Ex.INSTANCE.SetWindowLong( hwnd, GWLP_WNDPROC, defaultWndProc );
// show the OS window title bar
updateFrame();
updateFrame( 0 );
// cleanup
window = null;
}
private void updateFrame() {
private void updateFrame( int state ) {
// Following SetWindowPos() sends a WM_SIZE(SIZE_RESTORED) message to the window
// (although SWP_NOSIZE is set), which would prevent maximizing/minimizing
// when making the frame visible.
// AWT uses WM_SIZE wParam SIZE_RESTORED to update JFrame.extendedState and
// removes MAXIMIZED_BOTH and ICONIFIED. (see method AwtFrame::WmSize() in awt_Frame.cpp)
// To avoid this, change WM_SIZE wParam to SIZE_MAXIMIZED or SIZE_MINIMIZED if necessary.
if( (state & JFrame.ICONIFIED) != 0 )
wmSizeWParam = SIZE_MINIMIZED;
else if( (state & JFrame.MAXIMIZED_BOTH) == JFrame.MAXIMIZED_BOTH )
wmSizeWParam = SIZE_MAXIMIZED;
else
wmSizeWParam = -1;
// this sends WM_NCCALCSIZE and removes/shows the window title bar
User32.INSTANCE.SetWindowPos( hwnd, hwnd, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
wmSizeWParam = -1;
}
/**
@@ -391,6 +403,11 @@ public class FlatWindowsNativeWindowBorder
fireStateChangedLaterOnce();
break;
case WM_SIZE:
if( wmSizeWParam >= 0 )
wParam = new WPARAM( wmSizeWParam );
break;
case WM_DESTROY:
return WmDestroy( hwnd, uMsg, wParam, lParam );
}

View File

@@ -47,9 +47,9 @@ JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder
extern "C"
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_updateFrame
( JNIEnv* env, jobject obj, jlong hwnd )
( JNIEnv* env, jobject obj, jlong hwnd, jint state )
{
FlatWndProc::updateFrame( reinterpret_cast<HWND>( hwnd ) );
FlatWndProc::updateFrame( reinterpret_cast<HWND>( hwnd ), state );
}
extern "C"
@@ -68,6 +68,9 @@ jmethodID FlatWndProc::fireStateChangedLaterOnceMID;
HWNDMap* FlatWndProc::hwndMap;
#define java_awt_Frame_ICONIFIED 1
#define java_awt_Frame_MAXIMIZED_BOTH (4 | 2)
//---- class FlatWndProc methods ----------------------------------------------
FlatWndProc::FlatWndProc() {
@@ -76,6 +79,7 @@ FlatWndProc::FlatWndProc() {
obj = NULL;
hwnd = NULL;
defaultWndProc = NULL;
wmSizeWParam = -1;
}
HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
@@ -120,7 +124,7 @@ void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) {
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc );
// show the OS window title bar
updateFrame( hwnd );
updateFrame( hwnd, 0 );
// cleanup
env->DeleteGlobalRef( fwp->obj );
@@ -145,10 +149,29 @@ void FlatWndProc::initIDs( JNIEnv *env, jobject obj ) {
initialized = 1;
}
void FlatWndProc::updateFrame( HWND hwnd ) {
void FlatWndProc::updateFrame( HWND hwnd, int state ) {
// Following SetWindowPos() sends a WM_SIZE(SIZE_RESTORED) message to the window
// (although SWP_NOSIZE is set), which would prevent maximizing/minimizing
// when making the frame visible.
// AWT uses WM_SIZE wParam SIZE_RESTORED to update JFrame.extendedState and
// removes MAXIMIZED_BOTH and ICONIFIED. (see method AwtFrame::WmSize() in awt_Frame.cpp)
// To avoid this, change WM_SIZE wParam to SIZE_MAXIMIZED or SIZE_MINIMIZED if necessary.
FlatWndProc* fwp = (FlatWndProc*) hwndMap->get( hwnd );
if( fwp != NULL ) {
if( (state & java_awt_Frame_ICONIFIED) != 0 )
fwp->wmSizeWParam = SIZE_MINIMIZED;
else if( (state & java_awt_Frame_MAXIMIZED_BOTH) == java_awt_Frame_MAXIMIZED_BOTH )
fwp->wmSizeWParam = SIZE_MAXIMIZED;
else
fwp->wmSizeWParam = -1;
}
// this sends WM_NCCALCSIZE and removes/shows the window title bar
::SetWindowPos( hwnd, hwnd, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
if( fwp != NULL )
fwp->wmSizeWParam = -1;
}
LRESULT CALLBACK FlatWndProc::StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
@@ -176,6 +199,11 @@ LRESULT CALLBACK FlatWndProc::WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, L
fireStateChangedLaterOnce();
break;
case WM_SIZE:
if( wmSizeWParam >= 0 )
wParam = wmSizeWParam;
break;
case WM_DESTROY:
return WmDestroy( hwnd, uMsg, wParam, lParam );
}

View File

@@ -25,7 +25,7 @@ class FlatWndProc
public:
static HWND install( JNIEnv *env, jobject obj, jobject window );
static void uninstall( JNIEnv *env, jobject obj, HWND hwnd );
static void updateFrame( HWND hwnd );
static void updateFrame( HWND hwnd, int state );
private:
static int initialized;
@@ -40,6 +40,7 @@ private:
jobject obj;
HWND hwnd;
WNDPROC defaultWndProc;
int wmSizeWParam;
FlatWndProc();
static void initIDs( JNIEnv *env, jobject obj );

View File

@@ -34,10 +34,10 @@ JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder
/*
* Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc
* Method: updateFrame
* Signature: (J)V
* Signature: (JI)V
*/
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_updateFrame
(JNIEnv *, jobject, jlong);
(JNIEnv *, jobject, jlong, jint);
/*
* Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc