Window decorations: reworked/fixed initialization when running in JetBrains Runtime

This commit is contained in:
Karl Tauber
2020-06-26 00:22:28 +02:00
parent 293b76f04b
commit 7720d42584
3 changed files with 77 additions and 54 deletions

View File

@@ -48,11 +48,25 @@ import com.formdev.flatlaf.util.SystemInfo;
/** /**
* Provides the Flat LaF UI delegate for {@link javax.swing.JRootPane}. * Provides the Flat LaF UI delegate for {@link javax.swing.JRootPane}.
* *
* <!-- FlatRootPaneUI -->
*
* @uiDefault RootPane.border Border
*
* <!-- FlatWindowResizer -->
*
* @uiDefault RootPane.borderDragThickness int
* @uiDefault RootPane.cornerDragWidth int
* @uiDefault RootPane.honorMinimumSizeOnResize boolean
*
* @author Karl Tauber * @author Karl Tauber
*/ */
public class FlatRootPaneUI public class FlatRootPaneUI
extends BasicRootPaneUI extends BasicRootPaneUI
{ {
// check this field before using class JBRCustomDecorations to avoid unnecessary loading of that class
static final boolean canUseJBRCustomDecorations
= SystemInfo.IS_JETBRAINS_JVM_11_OR_LATER && SystemInfo.IS_WINDOWS_10_OR_LATER;
private JRootPane rootPane; private JRootPane rootPane;
private FlatTitlePane titlePane; private FlatTitlePane titlePane;
private LayoutManager oldLayout; private LayoutManager oldLayout;
@@ -71,7 +85,7 @@ public class FlatRootPaneUI
if( rootPane.getWindowDecorationStyle() != JRootPane.NONE ) if( rootPane.getWindowDecorationStyle() != JRootPane.NONE )
installClientDecorations(); installClientDecorations();
if( SystemInfo.IS_JETBRAINS_JVM_11_OR_LATER && SystemInfo.IS_WINDOWS_10_OR_LATER ) if( canUseJBRCustomDecorations )
JBRCustomDecorations.install( rootPane ); JBRCustomDecorations.install( rootPane );
} }
@@ -108,8 +122,10 @@ public class FlatRootPaneUI
} }
private void installClientDecorations() { private void installClientDecorations() {
boolean isJBRSupported = canUseJBRCustomDecorations && JBRCustomDecorations.isSupported();
// install border // install border
if( rootPane.getWindowDecorationStyle() != JRootPane.NONE && !JBRCustomDecorations.isSupported() ) if( rootPane.getWindowDecorationStyle() != JRootPane.NONE && !isJBRSupported )
LookAndFeel.installBorder( rootPane, "RootPane.border" ); LookAndFeel.installBorder( rootPane, "RootPane.border" );
else else
LookAndFeel.uninstallBorder( rootPane ); LookAndFeel.uninstallBorder( rootPane );
@@ -122,7 +138,7 @@ public class FlatRootPaneUI
rootPane.setLayout( new FlatRootLayout() ); rootPane.setLayout( new FlatRootLayout() );
// install window resizer // install window resizer
if( !JBRCustomDecorations.isSupported() ) if( !isJBRSupported )
windowResizer = new FlatWindowResizer( rootPane ); windowResizer = new FlatWindowResizer( rootPane );
} }

View File

@@ -446,7 +446,9 @@ class FlatTitlePane
} }
private boolean hasJBRCustomDecoration() { private boolean hasJBRCustomDecoration() {
return window != null && JBRCustomDecorations.hasCustomDecoration( window ); return window != null &&
FlatRootPaneUI.canUseJBRCustomDecorations &&
JBRCustomDecorations.hasCustomDecoration( window );
} }
private void updateJBRHitTestSpotsAndTitleBarHeight() { private void updateJBRHitTestSpotsAndTitleBarHeight() {

View File

@@ -68,36 +68,50 @@ public class JBRCustomDecorations
} }
static void install( JRootPane rootPane ) { static void install( JRootPane rootPane ) {
boolean frameIsDefaultLookAndFeelDecorated = JFrame.isDefaultLookAndFeelDecorated();
boolean dialogIsDefaultLookAndFeelDecorated = JDialog.isDefaultLookAndFeelDecorated();
boolean lafSupportsWindowDecorations = UIManager.getLookAndFeel().getSupportsWindowDecorations();
// check whether decorations are enabled
if( !frameIsDefaultLookAndFeelDecorated && !dialogIsDefaultLookAndFeelDecorated )
return;
// do not enable JBR decorations if JFrame and JDialog will use LaF decorations
if( lafSupportsWindowDecorations &&
frameIsDefaultLookAndFeelDecorated &&
dialogIsDefaultLookAndFeelDecorated )
return;
if( !isSupported() ) if( !isSupported() )
return; return;
// use hierarchy listener to wait until the root pane is added to a window // check whether root pane already has a parent, which is the case when switching LaF
if( rootPane.getParent() != null )
return;
// Use hierarchy listener to wait until the root pane is added to a window.
// Enabling JBR decorations must be done very early, probably before
// window becomes displayable (window.isDisplayable()). Tried also using
// "ancestor" property change event on root pane, but this is invoked too late.
HierarchyListener addListener = new HierarchyListener() { HierarchyListener addListener = new HierarchyListener() {
@Override @Override
public void hierarchyChanged( HierarchyEvent e ) { public void hierarchyChanged( HierarchyEvent e ) {
if( (e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) == 0 ) if( e.getChanged() != rootPane || (e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) == 0 )
return; return;
Container parent = e.getChangedParent(); Container parent = e.getChangedParent();
if( parent instanceof JFrame ) { if( parent instanceof Window )
JFrame frame = (JFrame) parent; install( (Window) parent );
// do not enable JBR decorations if JFrame will use LaF decorations // use invokeLater to remove listener to avoid that listener
if( lafSupportsWindowDecorations && frameIsDefaultLookAndFeelDecorated ) // is removed while listener queue is processed
EventQueue.invokeLater( () -> {
rootPane.removeHierarchyListener( this );
} );
}
};
rootPane.addHierarchyListener( addListener );
}
static void install( Window window ) {
if( !isSupported() )
return;
// do not enable JBR decorations if LaF provides decorations
if( UIManager.getLookAndFeel().getSupportsWindowDecorations() )
return;
if( window instanceof JFrame ) {
JFrame frame = (JFrame) window;
// do not enable JBR decorations if JFrame should use system window decorations
if( !JFrame.isDefaultLookAndFeelDecorated() )
return; return;
// do not enable JBR decorations if frame is undecorated // do not enable JBR decorations if frame is undecorated
@@ -108,13 +122,13 @@ public class JBRCustomDecorations
setHasCustomDecoration( frame ); setHasCustomDecoration( frame );
// enable Swing window decoration // enable Swing window decoration
rootPane.setWindowDecorationStyle( JRootPane.FRAME ); frame.getRootPane().setWindowDecorationStyle( JRootPane.FRAME );
} else if( parent instanceof JDialog ) { } else if( window instanceof JDialog ) {
JDialog dialog = (JDialog)parent; JDialog dialog = (JDialog) window;
// do not enable JBR decorations if JDialog will use LaF decorations // do not enable JBR decorations if JDialog should use system window decorations
if( lafSupportsWindowDecorations && dialogIsDefaultLookAndFeelDecorated ) if( !JDialog.isDefaultLookAndFeelDecorated() )
return; return;
// do not enable JBR decorations if dialog is undecorated // do not enable JBR decorations if dialog is undecorated
@@ -125,17 +139,8 @@ public class JBRCustomDecorations
setHasCustomDecoration( dialog ); setHasCustomDecoration( dialog );
// enable Swing window decoration // enable Swing window decoration
rootPane.setWindowDecorationStyle( JRootPane.PLAIN_DIALOG ); dialog.getRootPane().setWindowDecorationStyle( JRootPane.PLAIN_DIALOG );
} }
// use invokeLater to remove listener to avoid that listener
// is removed while listener queue is processed
EventQueue.invokeLater( () -> {
rootPane.removeHierarchyListener( this );
} );
}
};
rootPane.addHierarchyListener( addListener );
} }
static boolean hasCustomDecoration( Window window ) { static boolean hasCustomDecoration( Window window ) {