diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f0cf739..d7e71b92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ FlatLaf Change Log - Native window decorations: Fixed missing animations when minimizing, maximizing or restoring a window using window title bar buttons. (issue #282) +- Native window decorations: Fixed broken maximizing window when restoring frame + state at startup. (issue #283) - Native window decorations: Fixed double window title bar when first disposing a window with `frame.dispose()` and then showing it again with `frame.setVisible(true)`. (issue #277) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatWindowsNativeWindowBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatWindowsNativeWindowBorder.java index bc1b4165..0ae91536 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatWindowsNativeWindowBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatWindowsNativeWindowBorder.java @@ -309,6 +309,18 @@ class FlatWindowsNativeWindowBorder this.window = window; hwnd = installImpl( window ); + + // 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( hwnd ); + }); + } else + updateFrame( hwnd ); } void uninstall() { @@ -320,6 +332,7 @@ class FlatWindowsNativeWindowBorder private native long installImpl( Window window ); private native void uninstallImpl( long hwnd ); + private native void updateFrame( long hwnd ); private native void showWindow( long hwnd, int cmd ); // invoked from native code 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 9765750d..87bb06f0 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 @@ -338,7 +338,16 @@ public class FlatWindowsNativeWindowBorder defaultWndProc = User32Ex.INSTANCE.SetWindowLong( hwnd, GWLP_WNDPROC, this ); // remove the OS window title bar - updateFrame(); + 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(); } void uninstall() { @@ -358,7 +367,7 @@ public class FlatWindowsNativeWindowBorder private void updateFrame() { // 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_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); } /** 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 dfe4220c..db545406 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.cpp +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.cpp @@ -45,9 +45,16 @@ JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder FlatWndProc::uninstall( env, obj, reinterpret_cast( hwnd ) ); } +extern "C" +JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_updateFrame + ( JNIEnv* env, jobject obj, jlong hwnd ) +{ + FlatWndProc::updateFrame( reinterpret_cast( hwnd ) ); +} + extern "C" JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_showWindow - ( JNIEnv *env, jobject obj, jlong hwnd, jint cmd ) + ( JNIEnv* env, jobject obj, jlong hwnd, jint cmd ) { ::ShowWindow( reinterpret_cast( hwnd ), cmd ); } @@ -96,9 +103,6 @@ HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) { fwp->defaultWndProc = reinterpret_cast( ::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) FlatWndProc::StaticWindowProc ) ); - // remove the OS window title bar - fwp->updateFrame(); - return hwnd; } @@ -116,7 +120,7 @@ void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) { ::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc ); // show the OS window title bar - fwp->updateFrame(); + updateFrame( hwnd ); // cleanup env->DeleteGlobalRef( fwp->obj ); @@ -141,10 +145,10 @@ void FlatWndProc::initIDs( JNIEnv *env, jobject obj ) { initialized = 1; } -void FlatWndProc::updateFrame() { +void FlatWndProc::updateFrame( HWND hwnd ) { // 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_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ); } LRESULT CALLBACK FlatWndProc::StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { 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 a6d5bfbf..6c7bc675 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.h +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/cpp/FlatWndProc.h @@ -25,6 +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 ); private: static int initialized; @@ -42,7 +43,6 @@ private: FlatWndProc(); static void initIDs( JNIEnv *env, jobject obj ); - void updateFrame(); static LRESULT CALLBACK StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); diff --git a/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc.h b/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc.h index 76a35d16..fe37a2f7 100644 --- a/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc.h +++ b/flatlaf-natives/flatlaf-natives-windows/src/main/headers/com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc.h @@ -31,6 +31,14 @@ JNIEXPORT jlong JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorde JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_uninstallImpl (JNIEnv *, jobject, jlong); +/* + * Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc + * Method: updateFrame + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_updateFrame + (JNIEnv *, jobject, jlong); + /* * Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc * Method: showWindow diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatNativeWindowBorderTest.java b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatNativeWindowBorderTest.java index f9defb56..7ece92dd 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatNativeWindowBorderTest.java +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatNativeWindowBorderTest.java @@ -71,7 +71,7 @@ public class FlatNativeWindowBorderTest frame.dispose(); }, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); - frame.pack(); + frame.setSize( new Dimension( 800, 600 ) ); frame.setLocationRelativeTo( null ); int offset = 20 * Window.getWindows().length; frame.setLocation( frame.getX() + offset, frame.getY() + offset ); @@ -88,7 +88,7 @@ public class FlatNativeWindowBorderTest dialog.dispose(); }, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); - dialog.pack(); + dialog.setSize( new Dimension( 800, 600 ) ); dialog.setLocationRelativeTo( owner ); dialog.setLocation( dialog.getX() + 20, dialog.getY() + 20 ); dialog.setVisible( true ); @@ -104,7 +104,6 @@ public class FlatNativeWindowBorderTest hideWindowButton.setEnabled( false ); setBorder( new FlatLineBorder( new Insets( 0, 0, 0, 0 ), Color.red ) ); - setPreferredSize( new Dimension( 800, 600 ) ); updateInfo();