diff --git a/CHANGELOG.md b/CHANGELOG.md index fec8d763..01386b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ FlatLaf Change Log ## 1.2-SNAPSHOT +#### New features and improvements + +- Native window decorations: Support disabling native window decorations per + window. (set client property `JRootPane.useWindowDecorations` to `false` on + root pane). + #### Fixed bugs - Native window decorations: Fixed double window title bar when first disposing diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java index 9e198fda..6a82e2ac 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/FlatClientProperties.java @@ -231,10 +231,28 @@ public interface FlatClientProperties //---- JRootPane ---------------------------------------------------------- + /** + * Specifies whether FlatLaf native window decorations should be used + * when creating {@code JFrame} or {@code JDialog}. + *

+ * Setting this to {@code false} disables using FlatLaf native window decorations + * for the window that contains the root pane. Needs to be set before showing the window. + *

+ * (requires Window 10) + *

+ * Component {@link javax.swing.JRootPane}
+ * Value type {@link java.lang.Boolean} + * + * @since 1.1.1 + */ + String USE_WINDOW_DECORATIONS = "JRootPane.useWindowDecorations"; + /** * Specifies whether the menu bar is embedded into the title pane if custom * window decorations are enabled. Default is {@code true}. *

+ * (requires Window 10) + *

* Component {@link javax.swing.JRootPane}
* Value type {@link java.lang.Boolean} */ diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowBorder.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowBorder.java index 4a720492..1c21a5de 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowBorder.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatNativeWindowBorder.java @@ -27,6 +27,7 @@ import javax.swing.JRootPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.ChangeListener; +import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatLaf; import com.formdev.flatlaf.FlatSystemProperties; import com.formdev.flatlaf.ui.JBRCustomDecorations.JBRWindowTopBorder; @@ -99,6 +100,10 @@ public class FlatNativeWindowBorder if( window instanceof JFrame ) { JFrame frame = (JFrame) window; + // check whether disabled via client property + if( !FlatClientProperties.clientPropertyBoolean( frame.getRootPane(), FlatClientProperties.USE_WINDOW_DECORATIONS, true ) ) + return; + // do not enable native window border if JFrame should use system window decorations // and if not forced to use FlatLaf/JBR native window decorations if( !JFrame.isDefaultLookAndFeelDecorated() && @@ -119,6 +124,10 @@ public class FlatNativeWindowBorder } else if( window instanceof JDialog ) { JDialog dialog = (JDialog) window; + // check whether disabled via client property + if( !FlatClientProperties.clientPropertyBoolean( dialog.getRootPane(), FlatClientProperties.USE_WINDOW_DECORATIONS, true ) ) + return; + // do not enable native window border if JDialog should use system window decorations // and if not forced to use FlatLaf/JBR native window decorations if( !JDialog.isDefaultLookAndFeelDecorated() && 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 307c6ba2..d41adbc0 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 @@ -28,6 +28,7 @@ import java.util.WeakHashMap; import javax.swing.*; import javax.swing.plaf.metal.MetalLookAndFeel; import javax.swing.plaf.nimbus.NimbusLookAndFeel; +import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatDarculaLaf; import com.formdev.flatlaf.FlatDarkLaf; import com.formdev.flatlaf.FlatIntelliJLaf; @@ -303,6 +304,12 @@ public class FlatNativeWindowBorderTest FlatNativeWindowBorder.setHasCustomDecoration( window, nativeCheckBox.isSelected() ); } + private void native2Changed() { + ((RootPaneContainer)window).getRootPane().putClientProperty( FlatClientProperties.USE_WINDOW_DECORATIONS, native2CheckBox.isSelected() ); + window.dispose(); + window.setVisible( true ); + } + private void revalidateLayout() { window.revalidate(); } @@ -372,6 +379,7 @@ public class FlatNativeWindowBorderTest undecoratedCheckBox = new JCheckBox(); fullScreenCheckBox = new JCheckBox(); nativeCheckBox = new JCheckBox(); + native2CheckBox = new JCheckBox(); openDialogButton = new JButton(); hideWindowButton = new JButton(); reopenButton = new JButton(); @@ -433,6 +441,12 @@ public class FlatNativeWindowBorderTest nativeCheckBox.addActionListener(e -> nativeChanged()); add(nativeCheckBox, "cell 0 3 3 1"); + //---- native2CheckBox ---- + native2CheckBox.setText("JRootPane.useWindowDecorations"); + native2CheckBox.setSelected(true); + native2CheckBox.addActionListener(e -> native2Changed()); + add(native2CheckBox, "cell 0 3 3 1"); + //---- openDialogButton ---- openDialogButton.setText("Open Dialog"); openDialogButton.setMnemonic('D'); @@ -490,6 +504,7 @@ public class FlatNativeWindowBorderTest private JCheckBox undecoratedCheckBox; private JCheckBox fullScreenCheckBox; private JCheckBox nativeCheckBox; + private JCheckBox native2CheckBox; private JButton openDialogButton; private JButton hideWindowButton; private JButton reopenButton; diff --git a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatNativeWindowBorderTest.jfd b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatNativeWindowBorderTest.jfd index dcf543c0..56f5faa3 100644 --- a/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatNativeWindowBorderTest.jfd +++ b/flatlaf-testing/src/main/java/com/formdev/flatlaf/testing/FlatNativeWindowBorderTest.jfd @@ -65,6 +65,14 @@ new FormModel { }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { "value": "cell 0 3 3 1" } ) + add( new FormComponent( "javax.swing.JCheckBox" ) { + name: "native2CheckBox" + "text": "JRootPane.useWindowDecorations" + "selected": true + addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "native2Changed", false ) ) + }, new FormLayoutConstraints( class net.miginfocom.layout.CC ) { + "value": "cell 0 3 3 1" + } ) add( new FormComponent( "javax.swing.JButton" ) { name: "openDialogButton" "text": "Open Dialog"