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

This commit is contained in:
Karl Tauber
2021-03-25 10:32:24 +01:00
parent 8a6a0c7971
commit c24ce7c5bc
7 changed files with 48 additions and 13 deletions

View File

@@ -13,6 +13,8 @@ FlatLaf Change Log
- Native window decorations: Fixed missing animations when minimizing, - Native window decorations: Fixed missing animations when minimizing,
maximizing or restoring a window using window title bar buttons. (issue #282) 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 - Native window decorations: Fixed double window title bar when first disposing
a window with `frame.dispose()` and then showing it again with a window with `frame.dispose()` and then showing it again with
`frame.setVisible(true)`. (issue #277) `frame.setVisible(true)`. (issue #277)

View File

@@ -309,6 +309,18 @@ class FlatWindowsNativeWindowBorder
this.window = window; this.window = window;
hwnd = installImpl( 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() { void uninstall() {
@@ -320,6 +332,7 @@ class FlatWindowsNativeWindowBorder
private native long installImpl( Window window ); private native long installImpl( Window window );
private native void uninstallImpl( long hwnd ); private native void uninstallImpl( long hwnd );
private native void updateFrame( long hwnd );
private native void showWindow( long hwnd, int cmd ); private native void showWindow( long hwnd, int cmd );
// invoked from native code // invoked from native code

View File

@@ -338,7 +338,16 @@ public class FlatWindowsNativeWindowBorder
defaultWndProc = User32Ex.INSTANCE.SetWindowLong( hwnd, GWLP_WNDPROC, this ); defaultWndProc = User32Ex.INSTANCE.SetWindowLong( hwnd, GWLP_WNDPROC, this );
// remove the OS window title bar // 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() { void uninstall() {
@@ -358,7 +367,7 @@ public class FlatWindowsNativeWindowBorder
private void updateFrame() { private void updateFrame() {
// this sends WM_NCCALCSIZE and removes/shows the window title bar // this sends WM_NCCALCSIZE and removes/shows the window title bar
User32.INSTANCE.SetWindowPos( hwnd, hwnd, 0, 0, 0, 0, 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 );
} }
/** /**

View File

@@ -45,9 +45,16 @@ JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder
FlatWndProc::uninstall( env, obj, reinterpret_cast<HWND>( hwnd ) ); FlatWndProc::uninstall( env, obj, reinterpret_cast<HWND>( 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>( hwnd ) );
}
extern "C" extern "C"
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_showWindow 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>( hwnd ), cmd ); ::ShowWindow( reinterpret_cast<HWND>( hwnd ), cmd );
} }
@@ -96,9 +103,6 @@ HWND FlatWndProc::install( JNIEnv *env, jobject obj, jobject window ) {
fwp->defaultWndProc = reinterpret_cast<WNDPROC>( fwp->defaultWndProc = reinterpret_cast<WNDPROC>(
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) FlatWndProc::StaticWindowProc ) ); ::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) FlatWndProc::StaticWindowProc ) );
// remove the OS window title bar
fwp->updateFrame();
return hwnd; return hwnd;
} }
@@ -116,7 +120,7 @@ void FlatWndProc::uninstall( JNIEnv *env, jobject obj, HWND hwnd ) {
::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc ); ::SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) fwp->defaultWndProc );
// show the OS window title bar // show the OS window title bar
fwp->updateFrame(); updateFrame( hwnd );
// cleanup // cleanup
env->DeleteGlobalRef( fwp->obj ); env->DeleteGlobalRef( fwp->obj );
@@ -141,10 +145,10 @@ void FlatWndProc::initIDs( JNIEnv *env, jobject obj ) {
initialized = 1; initialized = 1;
} }
void FlatWndProc::updateFrame() { void FlatWndProc::updateFrame( HWND hwnd ) {
// this sends WM_NCCALCSIZE and removes/shows the window title bar // this sends WM_NCCALCSIZE and removes/shows the window title bar
::SetWindowPos( hwnd, hwnd, 0, 0, 0, 0, ::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 ) { LRESULT CALLBACK FlatWndProc::StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {

View File

@@ -25,6 +25,7 @@ class FlatWndProc
public: public:
static HWND install( JNIEnv *env, jobject obj, jobject window ); static HWND install( JNIEnv *env, jobject obj, jobject window );
static void uninstall( JNIEnv *env, jobject obj, HWND hwnd ); static void uninstall( JNIEnv *env, jobject obj, HWND hwnd );
static void updateFrame( HWND hwnd );
private: private:
static int initialized; static int initialized;
@@ -42,7 +43,6 @@ private:
FlatWndProc(); FlatWndProc();
static void initIDs( JNIEnv *env, jobject obj ); static void initIDs( JNIEnv *env, jobject obj );
void updateFrame();
static LRESULT CALLBACK StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); static LRESULT CALLBACK StaticWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );

View File

@@ -31,6 +31,14 @@ JNIEXPORT jlong JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorde
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_uninstallImpl JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_uninstallImpl
(JNIEnv *, jobject, jlong); (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 * Class: com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_WndProc
* Method: showWindow * Method: showWindow

View File

@@ -71,7 +71,7 @@ public class FlatNativeWindowBorderTest
frame.dispose(); frame.dispose();
}, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); }, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
frame.pack(); frame.setSize( new Dimension( 800, 600 ) );
frame.setLocationRelativeTo( null ); frame.setLocationRelativeTo( null );
int offset = 20 * Window.getWindows().length; int offset = 20 * Window.getWindows().length;
frame.setLocation( frame.getX() + offset, frame.getY() + offset ); frame.setLocation( frame.getX() + offset, frame.getY() + offset );
@@ -88,7 +88,7 @@ public class FlatNativeWindowBorderTest
dialog.dispose(); dialog.dispose();
}, KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0, false ), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); }, 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.setLocationRelativeTo( owner );
dialog.setLocation( dialog.getX() + 20, dialog.getY() + 20 ); dialog.setLocation( dialog.getX() + 20, dialog.getY() + 20 );
dialog.setVisible( true ); dialog.setVisible( true );
@@ -104,7 +104,6 @@ public class FlatNativeWindowBorderTest
hideWindowButton.setEnabled( false ); hideWindowButton.setEnabled( false );
setBorder( new FlatLineBorder( new Insets( 0, 0, 0, 0 ), Color.red ) ); setBorder( new FlatLineBorder( new Insets( 0, 0, 0, 0 ), Color.red ) );
setPreferredSize( new Dimension( 800, 600 ) );
updateInfo(); updateInfo();