Native window decorations: fixed missing animations when minimizing, maximizing or restoring a window using window title bar buttons (issue #282)

This commit is contained in:
Karl Tauber
2021-03-24 23:59:59 +01:00
parent de6e5bd800
commit 8a6a0c7971
8 changed files with 68 additions and 6 deletions

View File

@@ -11,6 +11,8 @@ FlatLaf Change Log
#### Fixed bugs #### Fixed bugs
- Native window decorations: Fixed missing animations when minimizing,
maximizing or restoring a window using window title bar buttons. (issue #282)
- 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

@@ -226,6 +226,13 @@ public class FlatNativeWindowBorder
nativeProvider.setTitleBarAppIconBounds( window, appIconBounds ); nativeProvider.setTitleBarAppIconBounds( window, appIconBounds );
} }
static boolean showWindow( Window window, int cmd ) {
if( canUseJBRCustomDecorations || !isSupported() )
return false;
return nativeProvider.showWindow( window, cmd );
}
private static void initialize() { private static void initialize() {
if( supported != null ) if( supported != null )
return; return;
@@ -276,6 +283,13 @@ public class FlatNativeWindowBorder
void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots ); void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots );
void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds ); void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds );
// commands for showWindow(); values must match Win32 API
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
int SW_MAXIMIZE = 3;
int SW_MINIMIZE = 6;
int SW_RESTORE = 9;
boolean showWindow( Window window, int cmd );
boolean isColorizationColorAffectsBorders(); boolean isColorizationColorAffectsBorders();
Color getColorizationColor(); Color getColorizationColor();
int getColorizationColorBalance(); int getColorizationColorBalance();

View File

@@ -542,10 +542,12 @@ debug*/
* Iconifies the window. * Iconifies the window.
*/ */
protected void iconify() { protected void iconify() {
if( window instanceof Frame ) { if( !(window instanceof Frame) )
Frame frame = (Frame) window; return;
Frame frame = (Frame) window;
if( !FlatNativeWindowBorder.showWindow( window, FlatNativeWindowBorder.Provider.SW_MINIMIZE ) )
frame.setExtendedState( frame.getExtendedState() | Frame.ICONIFIED ); frame.setExtendedState( frame.getExtendedState() | Frame.ICONIFIED );
}
} }
/** /**
@@ -563,7 +565,8 @@ debug*/
rootPane.putClientProperty( "_flatlaf.maximizedBoundsUpToDate", true ); rootPane.putClientProperty( "_flatlaf.maximizedBoundsUpToDate", true );
// maximize window // maximize window
frame.setExtendedState( frame.getExtendedState() | Frame.MAXIMIZED_BOTH ); if( !FlatNativeWindowBorder.showWindow( frame, FlatNativeWindowBorder.Provider.SW_MAXIMIZE ) )
frame.setExtendedState( frame.getExtendedState() | Frame.MAXIMIZED_BOTH );
} }
protected void updateMaximizedBounds() { protected void updateMaximizedBounds() {
@@ -651,8 +654,11 @@ debug*/
* Restores the window size. * Restores the window size.
*/ */
protected void restore() { protected void restore() {
if( window instanceof Frame ) { if( !(window instanceof Frame) )
Frame frame = (Frame) window; return;
Frame frame = (Frame) window;
if( !FlatNativeWindowBorder.showWindow( window, FlatNativeWindowBorder.Provider.SW_RESTORE ) ) {
int state = frame.getExtendedState(); int state = frame.getExtendedState();
frame.setExtendedState( ((state & Frame.ICONIFIED) != 0) frame.setExtendedState( ((state & Frame.ICONIFIED) != 0)
? (state & ~Frame.ICONIFIED) ? (state & ~Frame.ICONIFIED)

View File

@@ -197,6 +197,16 @@ class FlatWindowsNativeWindowBorder
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null; wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null;
} }
@Override
public boolean showWindow( Window window, int cmd ) {
WndProc wndProc = windowsMap.get( window );
if( wndProc == null )
return false;
wndProc.showWindow( wndProc.hwnd, cmd );
return true;
}
@Override @Override
public boolean isColorizationColorAffectsBorders() { public boolean isColorizationColorAffectsBorders() {
updateColorization(); updateColorization();
@@ -310,6 +320,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 showWindow( long hwnd, int cmd );
// invoked from native code // invoked from native code
private int onNcHitTest( int x, int y, boolean isOnResizeBorder ) { private int onNcHitTest( int x, int y, boolean isOnResizeBorder ) {

View File

@@ -183,6 +183,16 @@ public class FlatWindowsNativeWindowBorder
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null; wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null;
} }
@Override
public boolean showWindow( Window window, int cmd ) {
WndProc wndProc = windowsMap.get( window );
if( wndProc == null )
return false;
User32.INSTANCE.ShowWindow( wndProc.hwnd, cmd );
return true;
}
@Override @Override
public boolean isColorizationColorAffectsBorders() { public boolean isColorizationColorAffectsBorders() {
updateColorization(); updateColorization();

View File

@@ -45,6 +45,13 @@ 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_showWindow
( JNIEnv *env, jobject obj, jlong hwnd, jint cmd )
{
::ShowWindow( reinterpret_cast<HWND>( hwnd ), cmd );
}
//---- class FlatWndProc fields ----------------------------------------------- //---- class FlatWndProc fields -----------------------------------------------
int FlatWndProc::initialized = 0; int FlatWndProc::initialized = 0;

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: showWindow
* Signature: (JI)V
*/
JNIEXPORT void JNICALL Java_com_formdev_flatlaf_ui_FlatWindowsNativeWindowBorder_00024WndProc_showWindow
(JNIEnv *, jobject, jlong, jint);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -153,6 +153,10 @@ public class FlatNativeWindowBorderTest
} }
} ); } );
window.addWindowStateListener( e -> {
System.out.println( windowId + " windowStateChanged " + e.getOldState() + " --> " + e.getNewState() );
} );
registerSwitchToLookAndFeel( "F1", FlatLightLaf.class.getName() ); registerSwitchToLookAndFeel( "F1", FlatLightLaf.class.getName() );
registerSwitchToLookAndFeel( "F2", FlatDarkLaf.class.getName() ); registerSwitchToLookAndFeel( "F2", FlatDarkLaf.class.getName() );
registerSwitchToLookAndFeel( "F3", FlatIntelliJLaf.class.getName() ); registerSwitchToLookAndFeel( "F3", FlatIntelliJLaf.class.getName() );